inifile.cc
main.cc
mkshort.cc
+ option.cc
parse.cc
rgbcolors.cc
route.cc
QString line;
gpsbabel::TextStream stream;
- stream.open(arcfileopt.get(), QIODevice::ReadOnly, MYNAME);
+ stream.open(arcfileopt, QIODevice::ReadOnly, MYNAME);
auto* arcpt1 = new Waypoint;
auto* arcpt2 = new Waypoint;
#include "defs.h" // for ARG_NOMINMAX, ARGTYPE_BOOL, Waypoint (ptr only)
#include "filter.h" // for Filter
-#include "option.h" // for OptionBool, OptionCString
+#include "option.h" // for OptionBool, OptionString
#if FILTERS_ENABLED
/* Data Members */
double pos_dist{};
- OptionCString distopt;
- OptionCString arcfileopt;
+ OptionDouble distopt;
+ OptionString arcfileopt;
OptionBool rteopt;
OptionBool trkopt;
OptionBool exclopt;
},
{
"distance", &distopt, "Maximum distance from arc",
- nullptr, ARGTYPE_FLOAT | ARGTYPE_REQUIRED, ARG_NOMINMAX, nullptr
+ nullptr, ARGTYPE_ALLOW_TRAILING_DATA | ARGTYPE_STRING | ARGTYPE_REQUIRED, ARG_NOMINMAX, nullptr
},
{
"exclude", &exclopt, "Exclude points close to the arc", nullptr,
*/
#include <cmath> // macos wants abs from here!
-#include <cstdlib> // for strtod, abs
+#include <cstdlib> // for abs
#include <utility> // for as_const
#include <QString> // for QString
{
maxDist = 0.0;
if (distopt) {
- maxDist = strtod(distopt, nullptr);
+ maxDist = distopt.get_result();
}
minAngle = 0.0;
if (minangleopt) {
- minAngle = strtod(minangleopt, nullptr);
+ minAngle = minangleopt.get_result();
}
route_backup(&routes_orig);
#include "defs.h" // for route_head (ptr only), ARGTYPE_FLOAT, ARG_NOMINMAX
#include "filter.h" // for Filter
-#include "option.h" // for OptionCString
+#include "option.h" // for OptionString
#if FILTERS_ENABLED
void deinit() override;
private:
- OptionCString distopt;
- OptionCString minangleopt;
+ OptionDouble distopt;
+ OptionDouble minangleopt;
double maxDist{};
double minAngle{};
* for "groups" of exactly one option. */
#define ARGTYPE_BEGIN_REQ 0x04000000U
#define ARGTYPE_END_REQ 0x02000000U
+/* For integer conversions specify the base to allow strict error checking and
+ * proper conversion in Vecs */
+#define ARGTYPE_BASE_10 0x00000000U
+#define ARGTYPE_BASE_AUTO 0x00100000U
+#define ARGTYPE_BASE_16 0x00200000U
+
+/* For integer and double conversions is trailing data allowed?
+ * This allows strict error checking in Vecs */
+#define ARGTYPE_ALLOW_TRAILING_DATA 0x00400000U
#define ARGTYPE_TYPEMASK 0x00000fffU
+#define ARGTYPE_BASEMASK 0x00300000U
#define ARGTYPE_FLAGMASK 0xfffff000U
#define ARG_NOMINMAX nullptr, nullptr
/*
* From parse.c
*/
+int parse_integer(const QString& str, const QString& id, bool* ok = nullptr, QString* end = nullptr, int base = 10);
+double parse_double(const QString& str, const QString& id, bool* ok = nullptr, QString* end = nullptr);
int parse_coordinates(const char* str, int datum, grid_type grid,
double* latitude, double* longitude, const char* module);
int parse_coordinates(const QString& str, int datum, grid_type grid,
double* latitude, double* longitude, const char* module);
-int parse_distance(const char* str, double* val, double scale, const char* module);
int parse_distance(const QString& str, double* val, double scale, const char* module);
-int parse_speed(const char* str, double* val, double scale, const char* module);
int parse_speed(const QString& str, double* val, double scale, const char* module);
/*
#include <QDebug> // for QDebug
#include <QRegularExpression> // for QRegularExpression, QRegularExpression::CaseInsensitiveOption, QRegularExpressionMatch
-#include <cstdlib> // for strtod
-
-#include "defs.h" // for Waypoint, fatal, route_head (ptr only), xstrtoi, del_marked_wpts, route_del_marked_wpts, route_disp_all, track_del_marked_wpts, track_disp_all, waypt_disp_all, fix_none, fix_unknown
+#include "defs.h" // for Waypoint, fatal, route_head (ptr only), del_marked_wpts, route_del_marked_wpts, route_disp_all, track_del_marked_wpts, track_disp_all, waypt_disp_all, fix_none, fix_unknown
#include "src/core/logging.h" // for FatalMsg
void DiscardFilter::init()
{
if (hdopopt) {
- hdopf = strtod(hdopopt, nullptr);
+ hdopf = hdopopt.get_result();
} else {
hdopf = -1.0;
}
if (vdopopt) {
- vdopf = strtod(vdopopt, nullptr);
+ vdopf = vdopopt.get_result();
} else {
vdopf = -1.0;
}
if (satopt) {
- satpf = xstrtoi(satopt, nullptr, 10);
+ satpf = satopt.get_result();
} else {
satpf = -1;
}
if (eleminopt) {
- eleminpf = xstrtoi(eleminopt, nullptr, 10);
+ eleminpf = eleminopt.get_result();
}
if (elemaxopt) {
- elemaxpf = xstrtoi(elemaxopt, nullptr, 10);
+ elemaxpf = elemaxopt.get_result();
}
if (nameopt) {
- name_regex = generateRegExp(nameopt.get());
+ name_regex = generateRegExp(nameopt);
if (!name_regex.isValid()) {
fatal(FatalMsg() << "discard: matchname option is an invalid expression.");
}
}
if (descopt) {
- desc_regex = generateRegExp(descopt.get());
+ desc_regex = generateRegExp(descopt);
if (!desc_regex.isValid()) {
fatal(FatalMsg() << "discard: matchdesc option is an invalid expression.");
}
}
if (cmtopt) {
- cmt_regex = generateRegExp(cmtopt.get());
+ cmt_regex = generateRegExp(cmtopt);
if (!cmt_regex.isValid()) {
fatal(FatalMsg() << "discard: matchcmt option is an invalid expression.");
}
}
if (iconopt) {
- icon_regex = generateRegExp(iconopt.get());
+ icon_regex = generateRegExp(iconopt);
if (!icon_regex.isValid()) {
fatal(FatalMsg() << "discard: matchicon option is an invalid expression.");
}
#include "defs.h" // for arglist_t, ARG_NOMINMAX, ARGTYPE_BEGIN_REQ, ARGTYPE_STRING, ARGTYPE_BOOL, ARGTYPE_INT, ARGTYPE_FLOAT, route_head, ARGTYPE_END_REQ, Waypoint, gpsdata_type
#include "filter.h" // for Filter
-#include "option.h" // for OptionCString, OptionBool
+#include "option.h" // for OptionString, OptionBool
#if FILTERS_ENABLED
class DiscardFilter:public Filter
/* Data Members */
- OptionCString hdopopt;
- OptionCString vdopopt;
+ OptionDouble hdopopt;
+ OptionDouble vdopopt;
OptionBool andopt;
- OptionCString satopt;
+ OptionInt satopt;
OptionBool fixnoneopt;
OptionBool fixunknownopt;
- OptionCString eleminopt;
- OptionCString elemaxopt;
- OptionCString nameopt;
+ OptionInt eleminopt;
+ OptionInt elemaxopt;
+ OptionString nameopt;
QRegularExpression name_regex;
- OptionCString descopt;
+ OptionString descopt;
QRegularExpression desc_regex;
- OptionCString cmtopt;
+ OptionString cmtopt;
QRegularExpression cmt_regex;
- OptionCString iconopt;
+ OptionString iconopt;
QRegularExpression icon_regex;
double hdopf{};
},
{
"sat", &satopt, "Minimum sats to keep points",
- "-1.0", ARGTYPE_BEGIN_REQ | ARGTYPE_INT, ARG_NOMINMAX, nullptr
+ "-1", ARGTYPE_BEGIN_REQ | ARGTYPE_INT, ARG_NOMINMAX, nullptr
},
{
"fixnone", &fixnoneopt, "Suppress points without fix",
}
if (offset_tag || opt_offsettime) {
- QByteArray time_tag = opt_offsettime? QByteArray(opt_offsettime) : exif_read_str(offset_tag);
+ QString time_tag = opt_offsettime? opt_offsettime : QString(exif_read_str(offset_tag));
// string should be +HH:MM or -HH:MM
static const QRegularExpression re(R"(^([+-])(\d{2}):(\d{2})$)");
assert(re.isValid());
} else if (opt_offsettime) {
// Only warn for user supplied offsets.
// Offset tags may indicate the offset was unknown, e.g. " : ".
- warning(MYNAME ": OffsetTime is expected to be +HH:MM or -HH:MM, but was %s.\n", time_tag.constData());
+ warning(MYNAME ": OffsetTime is expected to be +HH:MM or -HH:MM, but was %s.\n", qPrintable(time_tag));
}
}
{
if (exif_wpt_ref != nullptr) {
return;
- } else if ((wpt->shortname != nullptr) && (case_ignore_strcmp(wpt->shortname, opt_name.get()) == 0)) {
+ } else if ((wpt->shortname != nullptr) && (case_ignore_strcmp(wpt->shortname, opt_name) == 0)) {
exif_wpt_ref = wpt;
}
}
track_disp_all(nullptr, nullptr, exif_find_wpt_by_name_lambda);
}
if (exif_wpt_ref == nullptr) {
- warning(MYNAME ": No matching point with name \"%s\" found.\n", qPrintable(opt_name.get()));
+ warning(MYNAME ": No matching point with name \"%s\" found.\n", qPrintable(opt_name));
}
} else {
auto exif_find_wpt_by_time_lambda = [this](const Waypoint* waypointp)->void {
route_disp_all(nullptr, nullptr, exif_find_wpt_by_time_lambda);
waypt_disp_all(exif_find_wpt_by_time_lambda);
- qint64 frame = xstrtoi(opt_frame, nullptr, 10);
+ qint64 frame = opt_frame.get_result();
if (exif_wpt_ref == nullptr) {
warning(MYNAME ": No point with a valid timestamp found.\n");
#include "defs.h" // for arglist_t, ff_cap, Waypoint, ARG_NOMINMAX, ARGTYPE_BOOL, ff_cap_none, ARGTYPE_INT, ARGTYPE_STRING, ff_cap_read, ff_cap_write, ff_type, ff_type_file
#include "format.h" // for Format
#include "gbfile.h" // for gbfile, gbsize_t
-#include "option.h" // for OptionCString, OptionBool
+#include "option.h" // for OptionString, OptionBool
class ExifFormat : public Format
OptionBool opt_filename;
OptionBool opt_overwrite;
- OptionCString opt_frame;
- OptionCString opt_name;
- OptionCString opt_offsettime;
+ OptionInt opt_frame;
+ OptionString opt_name;
+ OptionString opt_offsettime;
QVector<arglist_t> exif_args = {
{ "filename", &opt_filename, "Set waypoint name to source filename", "Y", ARGTYPE_BOOL, ARG_NOMINMAX, nullptr },
#include <cmath> // for atan2, modf, sqrt
#include <cstdio> // for fprintf, fflush, snprintf, snprintf
#include <cstdint> // for int32_t
-#include <cstdlib> // for strtol
#include <cstring> // for memcpy, strlen, strncpy, strchr
#include <ctime> // for time_t
#include <utility> // for as_const
#include <QByteArray> // for QByteArray
#include <QChar> // for QChar
-#include <QList> // for QList<>::const_iterator
#include <QString> // for QString
#include <QTextCodec> // for QTextCodec
#include <Qt> // for CaseInsensitive
GarminFormat::rw_init(const QString& fname)
{
receiver_must_upper = true;
- const char* receiver_charset = "US-ASCII";
+ QByteArray receiver_charset = "US-ASCII";
/* Technically, even this is a little loose as spaces aren't allowed */
const char* valid_waypt_chars = MILITANT_VALID_WAYPT_CHARS " ";
return;
}
- if (categorybitsopt) {
- categorybits = strtol(categorybitsopt, nullptr, 0);
- }
+ category = categoryopt? (1 << (categoryopt.get_result() - 1)) : 0;
+ categorybits = categorybitsopt? categorybitsopt.get_result() : 0;
if (baudopt) {
- baud = strtol(baudopt, nullptr, 0);
+ baud = baudopt.get_result();
switch (baud) {
case 9600:
case 19200:
* If the user provided a short_length, override the calculated value.
*/
if (snlen) {
- mkshort_handle->set_length(xstrtoi(snlen, nullptr, 10));
+ mkshort_handle->set_length(snlen.get_result());
} else {
mkshort_handle->set_length(receiver_short_length);
}
* However, this is still used for garmin_fs_garmin_after_read,
* garmin_fs_garmin_before_write.
*/
- if (opt_codec != nullptr) {
+ if (opt_codec) {
// override expected codec with user supplied choice.
- receiver_charset = opt_codec;
+ receiver_charset = opt_codec.get().toUtf8();
}
codec = get_codec(receiver_charset);
if (global_opts.verbose_status) {
- fprintf(stdout, "receiver charset detected as %s.\r\n", receiver_charset);
+ fprintf(stdout, "receiver charset detected as %s.\r\n", receiver_charset.constData());
}
valid_chars = valid_waypt_chars;
tx_waylist[i]->lat = wpt->latitude;
if (deficon) {
- icon = gt_find_icon_number_from_desc(deficon.get(), PCX);
+ icon = gt_find_icon_number_from_desc(deficon, PCX);
} else {
if (!wpt->gc_data->get_icon().isEmpty()) {
icon = gt_find_icon_number_from_desc(wpt->gc_data->get_icon(), PCX);
tx_waylist[i]->time_populated = 1;
}
if (category) {
- tx_waylist[i]->category = 1 << (xstrtoi(category, nullptr, 10) - 1);
+ tx_waylist[i]->category = category;
}
if (categorybits) {
tx_waylist[i]->category = categorybits;
#include "jeeps/gpsdevice.h" // for gpsdevh
#include "jeeps/gpssend.h" // for GPS_PWay, GPS_SWay, GPS_PTrack, GPS_PPvt_Data, GPS_SLap
#include "mkshort.h" // for MakeShort
-#include "option.h" // for OptionCString, OptionBool
+#include "option.h" // for OptionString, OptionBool
class GarminFormat : public Format
OptionBool poweroff;
OptionBool eraset;
OptionBool resettime;
- OptionCString snlen;
+ OptionInt snlen;
OptionBool snwhiteopt;
- OptionCString deficon;
- OptionCString category;
- OptionCString categorybitsopt;
- OptionCString baudopt;
- OptionCString opt_codec;
+ OptionString deficon;
+ OptionInt categoryopt;
+ OptionInt categorybitsopt;
+ OptionInt baudopt;
+ OptionString opt_codec;
int baud = 0;
+ int category{};
int categorybits{};
bool receiver_must_upper = true;
QTextCodec* codec{nullptr};
nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr
},
{
- "category", &category, "Category number to use for written waypoints",
+ "category", &categoryopt, "Category number to use for written waypoints",
nullptr, ARGTYPE_INT, "1", "16", nullptr
},
{
"bitscategory", &categorybitsopt, "Bitmap of categories",
- nullptr, ARGTYPE_INT, "1", "65535", nullptr
+ nullptr, ARGTYPE_BASE_AUTO | ARGTYPE_INT, "1", "65535", nullptr
},
{
"baud", &baudopt, "Speed in bits per second of serial port (baud=9600)",
if (res1.strlen + 4 + res2.strlen + 4 != l0) {
fatal(MYNAME ": Error out of sync (wrong size %d/%d/%d) on field '%s'!", l0, res1.strlen, res2.strlen, field);
}
- if (opt_lang && (opt_lang == res1.lc)) {
+ if (opt_lang && (opt_lang.get().toUtf8() == res1.lc)) {
string = res1.str;
- } else if (opt_lang && (opt_lang == res2.lc)) {
+ } else if (opt_lang && (opt_lang.get().toUtf8() == res2.lc)) {
string = res2.str;
} else {
fatal(MYNAME ": Must select language code, %s and %s found.\n", res1.lc.constData(), res2.lc.constData());
#if 0
wpt->shortname.truncate(pidx);
#endif
- } else if ((opt_speed) && (!wpt->speed_has_value())) {
+ } else if (opt_speed && (!wpt->speed_has_value())) {
wpt->set_speed(defspeed);
}
- if ((opt_proximity) && (!wpt->proximity_has_value())) {
+ if (opt_proximity && (!wpt->proximity_has_value())) {
wpt->set_proximity(defproximity);
}
}
void
-GarminGPIFormat::write_category(const char* /*unused*/, const unsigned char* image, const int image_sz) const
+GarminGPIFormat::write_category(const QString& /*unused*/, const unsigned char* image, const int image_sz) const
{
int sz = wdata_compute_size(wdata);
sz += 8; /* string header */
- sz += str_from_unicode(opt_cat.get()).size();
+ sz += str_from_unicode(opt_cat).size();
gbfputint32(0x80009, fout);
if ((! opt_hide_bitmap) && image_sz) {
gbfputint32(sz, fout);
}
gbfputint32(sz, fout);
- write_string(str_from_unicode(opt_cat.get()), 1);
+ write_string(str_from_unicode(opt_cat), 1);
wdata_write(wdata);
}
void
-GarminGPIFormat::load_bitmap_from_file(const char* fname, const unsigned char** data, int* data_sz)
+GarminGPIFormat::load_bitmap_from_file(const QString& fname, const unsigned char** data, int* data_sz)
{
int i;
int sz;
gbfclose(f);
}
+char GarminGPIFormat::parse_units(const QString& str)
+{
+ char result;
+ if (str.startsWith('m', Qt::CaseInsensitive)) {
+ result = 'm';
+ } else if (str.startsWith('s', Qt::CaseInsensitive)) {
+ result = 's';
+ } else {
+ fatal(MYNAME ": Unknown units parameter (%s).\n", qPrintable(str));
+ }
+ return result;
+}
+
/*******************************************************************************
* %%% global callbacks called by gpsbabel main process %%% *
*******************************************************************************/
fatal(MYNAME ": Unsupported code page (%d). File is likely encrypted.\n", codepage);
}
- units = tolower(opt_units[0]);
- if ((units != 'm') && (units != 's')) {
- fatal(MYNAME ": Unknown units parameter (%c).\n", opt_units[0]);
- }
+ units = parse_units(opt_units);
}
void
codepage = 0;
for (int i = 1250; i <= 1257; i++) {
- if (QStringLiteral("windows-%1").arg(i).compare(QString(opt_writecodec), Qt::CaseInsensitive) == 0) {
+ if (QStringLiteral("windows-%1").arg(i).compare(opt_writecodec, Qt::CaseInsensitive) == 0) {
codepage = i;
break;
}
}
if (! codepage) {
- if (QString("utf8").compare(QString(opt_writecodec), Qt::CaseInsensitive) == 0) {
+ if (QStringLiteral("utf8").compare(opt_writecodec, Qt::CaseInsensitive) == 0) {
codepage = 65001;
}
}
if (! codepage) {
- warning(MYNAME ": Unsupported character set (%s)!\n", qPrintable(opt_writecodec.get()));
+ warning(MYNAME ": Unsupported character set (%s)!\n", qPrintable(opt_writecodec));
fatal(MYNAME ": Valid values are windows-1250 to windows-1257 and utf8.\n");
}
- codec = get_codec(opt_writecodec.getba());
+ codec = get_codec(opt_writecodec.get().toUtf8());
- units = tolower(opt_units[0]);
- if ((units != 'm') && (units != 's')) {
- fatal(MYNAME ": Unknown units parameter (%c).\n", opt_units[0]);
- }
+ units = parse_units(opt_units);
alerts = (opt_alerts) ? 1 : 0;
short_h = nullptr;
gbfclose(fout);
- if ((opt_sleep) && !gpsbabel_testmode()) { /* don't sleep during 'testo' */
- int sleep = xstrtoi(opt_sleep, nullptr, 10);
+ if (opt_sleep && !gpsbabel_testmode()) { /* don't sleep during 'testo' */
+ int sleep = opt_sleep.get_result();
if (sleep < 1) {
sleep = 1;
}
const unsigned char* image;
int image_sz;
- if (strlen(opt_cat) == 0) {
+ if (opt_cat.isEmpty()) {
fatal(MYNAME ": Can't write empty category!\n");
}
if (opt_hide_bitmap) {
image = nullptr;
image_sz = 0;
- } else if (opt_bitmap && *opt_bitmap) {
+ } else if (!opt_bitmap.isEmpty()) {
load_bitmap_from_file(opt_bitmap, &image, &image_sz);
} else {
image = gpi_bitmap; /* embedded GPSBabel icon in gpi format */
#include "garmin_fs.h" // for garmin_fs_t
#include "gbfile.h" // for gbfile
#include "mkshort.h" // for MakeShort
-#include "option.h" // for OptionCString, OptionBool
+#include "option.h" // for OptionString, OptionBool
class GarminGPIFormat : public Format
void wdata_check(writer_data_t* data) const;
int wdata_compute_size(writer_data_t* data) const;
void wdata_write(const writer_data_t* data) const;
- void write_category(const char* unused, const unsigned char* image, int image_sz) const;
+ void write_category(const QString& unused, const unsigned char* image, int image_sz) const;
void write_header() const;
void enum_waypt_cb(const Waypoint* ref) const;
- static void load_bitmap_from_file(const char* fname, const unsigned char** data, int* data_sz);
+ static void load_bitmap_from_file(const QString& fname, const unsigned char** data, int* data_sz);
+ static char parse_units(const QString& str);
QByteArray str_from_unicode(const QString& qstr) const {return codec->fromUnicode(qstr);}
QString str_to_unicode(const QByteArray& cstr) const {return codec->toUnicode(cstr);}
/* Data Members */
- OptionCString opt_cat;
+ OptionString opt_cat;
OptionBool opt_pos;
OptionBool opt_notes;
OptionBool opt_hide_bitmap;
OptionBool opt_descr;
- OptionCString opt_bitmap;
+ OptionString opt_bitmap;
OptionBool opt_unique;
OptionBool opt_alerts;
- OptionCString opt_units;
- OptionCString opt_speed;
- OptionCString opt_proximity;
- OptionCString opt_sleep;
- OptionCString opt_lang;
- OptionCString opt_writecodec;
+ OptionString opt_units;
+ OptionDouble opt_speed;
+ OptionDouble opt_proximity;
+ OptionInt opt_sleep;
+ OptionString opt_lang;
+ OptionString opt_writecodec;
double defspeed{}, defproximity{};
int alerts{};
},
{
"proximity", &opt_proximity, "Default proximity",
- nullptr, ARGTYPE_STRING, ARG_NOMINMAX, nullptr
+ nullptr, ARGTYPE_ALLOW_TRAILING_DATA | ARGTYPE_STRING, ARG_NOMINMAX, nullptr
},
{
"sleep", &opt_sleep, "After output job done sleep n second(s)",
},
{
"speed", &opt_speed, "Default speed",
- nullptr, ARGTYPE_STRING, ARG_NOMINMAX, nullptr
+ nullptr, ARGTYPE_ALLOW_TRAILING_DATA | ARGTYPE_STRING, ARG_NOMINMAX, nullptr
},
{
"unique", &opt_unique, "Create unique waypoint names (default = yes)",
/* helpers */
-const char*
-GarminTxtFormat::get_option_val(const char* option, const char* def)
-{
- const char* c = (option != nullptr) ? option : def;
- return c;
-}
-
void
GarminTxtFormat::init_date_and_time_format()
{
// This is old, and weird, code.. date_time_format is a global that's
// explicitly malloced and freed elsewhere. This isn't very C++ at all,
// but this format is on its deathbead for deprecation.
- const char* d = get_option_val(opt_date_format, kDefaultDateFormat);
- QString d1 = convert_human_date_format(d);
+ QString d1 = convert_human_date_format(opt_date_format);
- const char* t = get_option_val(opt_time_format, kDefaultTimeFormat);
- QString t1 = convert_human_time_format(t);
+ QString t1 = convert_human_time_format(opt_time_format);
date_time_format = QStringLiteral("%1 %2").arg(d1, t1);
}
void
GarminTxtFormat::garmin_txt_utc_option()
{
- if (opt_utc != nullptr) {
- if (case_ignore_strcmp(opt_utc.get(), "utc") == 0) {
- utc_offs = 0;
- } else {
- utc_offs = xstrtoi(opt_utc, nullptr, 10);
- }
- utc_offs *= (60 * 60);
+ if (opt_utc) {
+ utc_offs = opt_utc.get_result() * 60 * 60;
gtxt_flags.utc = 1;
}
}
fout = new gpsbabel::TextStream;
fout->open(fname, QIODevice::WriteOnly, MYNAME, "windows-1252");
- gtxt_flags.metric = (toupper(*get_option_val(opt_dist, "m")) == 'M');
- gtxt_flags.celsius = (toupper(*get_option_val(opt_temp, "c")) == 'C');
+ gtxt_flags.metric = opt_dist.get().startsWith("m", Qt::CaseInsensitive);
+ gtxt_flags.celsius = opt_temp.get().startsWith("c", Qt::CaseInsensitive);
init_date_and_time_format();
if (opt_precision) {
- precision = xstrtoi(opt_precision, nullptr, 10);
+ precision = opt_precision.get_result();
if (precision < 0) {
- fatal(MYNAME ": Invalid precision (%s)!", qPrintable(opt_precision.get()));
+ fatal(MYNAME ": Invalid precision (%s)!", qPrintable(opt_precision));
}
}
- QString datum_str = get_option_val(opt_datum, nullptr);
- QString grid_str = get_option_val(opt_grid, nullptr);
-
grid_index = grid_lat_lon_dmm;
- if (!grid_str.isEmpty()) {
+ if (!opt_grid.isEmpty()) {
bool ok;
- if (int i = grid_str.toInt(&ok); ok) {
+ if (int i = opt_grid.toInt(&ok); ok) {
grid_index = (grid_type) i;
if ((grid_index < GRID_INDEX_MIN) || (grid_index > GRID_INDEX_MAX))
- fatal(MYNAME ": Grid index out of range (%d..%d)!",
+ fatal(MYNAME ": Grid index out of range (%d..%d)!\n",
(int)GRID_INDEX_MIN, (int)GRID_INDEX_MAX);
} else {
- grid_index = gt_lookup_grid_type(grid_str, MYNAME);
+ grid_index = gt_lookup_grid_type(opt_grid, MYNAME);
}
}
datum_index = kDatumWGS84;
break;
default:
- datum_index = gt_lookup_datum_index(datum_str, MYNAME);
+ datum_index = gt_lookup_datum_index(opt_datum, MYNAME);
}
garmin_txt_utc_option();
#include "defs.h"
#include "format.h" // for Format
-#include "option.h" // for OptionCString
+#include "option.h" // for OptionString
#include "src/core/textstream.h" // for TextStream
/* Constants */
static constexpr double kGarminUnknownAlt = 1.0e25;
- static constexpr char kDefaultDateFormat[] = "dd/mm/yyyy";
- static constexpr char kDefaultTimeFormat[] = "HH:mm:ss";
static const QVector<QString> headers;
/* Member Functions */
static bool is_valid_alt(double alt);
- static const char* get_option_val(const char* option, const char* def);
void init_date_and_time_format();
void convert_datum(const Waypoint* wpt, double* dest_lat, double* dest_lon) const;
void enum_waypt_cb(const Waypoint* wpt);
std::array<QList<std::pair<QString, int>>, unknown_header> header_mapping_info;
QStringList header_column_names;
- OptionCString opt_datum;
- OptionCString opt_dist;
- OptionCString opt_temp;
- OptionCString opt_date_format;
- OptionCString opt_time_format;
- OptionCString opt_precision;
- OptionCString opt_utc;
- OptionCString opt_grid;
+ OptionString opt_datum;
+ OptionString opt_dist;
+ OptionString opt_temp;
+ OptionString opt_date_format;
+ OptionString opt_time_format;
+ OptionInt opt_precision;
+ OptionInt opt_utc;
+ OptionString opt_grid;
QVector<arglist_t> garmin_txt_args = {
- {"date", &opt_date_format, "Read/Write date format (i.e. yyyy/mm/dd)", nullptr, ARGTYPE_STRING, ARG_NOMINMAX, nullptr},
+ {"date", &opt_date_format, "Read/Write date format (i.e. yyyy/mm/dd)", "dd/mm/yyyy", ARGTYPE_STRING, ARG_NOMINMAX, nullptr},
{"datum", &opt_datum, "GPS datum (def. WGS 84)", "WGS 84", ARGTYPE_STRING, ARG_NOMINMAX, nullptr},
{"dist", &opt_dist, "Distance unit [m=metric, s=statute]", "m", ARGTYPE_STRING, ARG_NOMINMAX, nullptr},
{"grid", &opt_grid, "Write position using this grid.", nullptr, ARGTYPE_STRING, ARG_NOMINMAX, nullptr},
{"prec", &opt_precision, "Precision of coordinates", "3", ARGTYPE_INT, ARG_NOMINMAX, nullptr},
{"temp", &opt_temp, "Temperature unit [c=Celsius, f=Fahrenheit]", "c", ARGTYPE_STRING, ARG_NOMINMAX, nullptr},
- {"time", &opt_time_format, "Read/Write time format (i.e. HH:mm:ss xx)", nullptr, ARGTYPE_STRING, ARG_NOMINMAX, nullptr},
+ {"time", &opt_time_format, "Read/Write time format (i.e. HH:mm:ss xx)", "HH:mm:ss", ARGTYPE_STRING, ARG_NOMINMAX, nullptr},
{"utc", &opt_utc, "Write timestamps with offset x to UTC time", nullptr, ARGTYPE_INT, "-23", "+23", nullptr},
};
// get the option for the processing the track name
if (opt_trk_header) {
- method = xstrtoi(opt_trk_header, nullptr, 10);
+ method = opt_trk_header.get_result();
// if method is out of range set to default
if ((method < 0) || (method > 1)) {
method = 0;
// get the option for the processing the track name
if (opt_trk_header) {
- method = xstrtoi(opt_trk_header, nullptr, 10);
+ method = opt_trk_header.get_result();
}
if (! track) {
GarminXTFormat::read()
{
// Saved Tracks file
- if (strcmp(opt_xt_ftype, "STRK") == 0) {
+ if (opt_xt_ftype.get() == "STRK") {
format_garmin_xt_proc_strk();
} else { // Active Track file
format_garmin_xt_proc_atrk();
#include "defs.h"
#include "format.h" // for Format
#include "gbfile.h" // for gbfile
-#include "option.h" // for OptionCString
+#include "option.h" // for OptionString
class GarminXTFormat : public Format
gbfile* fin{};
route_head* track{};
- OptionCString opt_xt_ftype;
- OptionCString opt_trk_header;
+ OptionString opt_xt_ftype;
+ OptionInt opt_trk_header;
QVector<arglist_t> format_garmin_xt_args = {
{"ftype", &opt_xt_ftype, "Garmin Mobile XT ([ATRK]/STRK)", "ATRK", ARGTYPE_STRING | ARGTYPE_REQUIRED, ARG_NOMINMAX, nullptr},
#include <cmath> // for fabs
#include <cstdio> // for printf, SEEK_SET
-#include <cstdlib> // for strtol
#include <cstring> // for memset, strstr, strcmp
#include <iterator> // for next
-#include "defs.h" // for Waypoint, warning, route_head, fatal, UrlLink, bounds, UrlList, unknown_alt, xfree, waypt_add_to_bounds, waypt_init_bounds, xstrtoi, route_add_wpt, route_disp_all, waypt_bounds_valid, xmalloc, gb_color, WaypointList, find_wa...
+#include "defs.h" // for Waypoint, warning, route_head, fatal, UrlLink, bounds, UrlList, unknown_alt, xfree, waypt_add_to_bounds, waypt_init_bounds, route_add_wpt, route_disp_all, waypt_bounds_valid, xmalloc, gb_color, WaypointList, find_wa...
#include "formspec.h" // for FormatSpecificDataList
#include "garmin_fs.h" // for garmin_fs_t, garmin_ilink_t
#include "garmin_tables.h" // for gt_waypt_class_map_point, gt_color_index_by_rgb, gt_color_value, gt_waypt_classes_e, gt_find_desc_from_icon_number, gt_find_icon_number_from_desc, gt_gdb_display_mode_symbol, gt_get_icao_country, gt_waypt_class_user_waypoint, GDB, gt_display_mode_symbol
fout = gbfopen_le(fname, "wb", MYNAME);
ftmp = gbfopen_le(nullptr, "wb", MYNAME);
- gdb_category = (gdb_opt_category) ? xstrtoi(gdb_opt_category, nullptr, 10) : 0;
- gdb_ver = (gdb_opt_ver && *gdb_opt_ver) ? xstrtoi(gdb_opt_ver, nullptr, 10) : 0;
+ gdb_category = gdb_opt_category ? gdb_opt_category.get_result() : 0;
+ gdb_ver = gdb_opt_ver.get_result();
if (gdb_category) {
if ((gdb_category < 1) || (gdb_category > 16)) {
}
if (gdb_opt_bitcategory) {
- gdb_category = strtol(gdb_opt_bitcategory, nullptr, 0);
+ gdb_category = gdb_opt_bitcategory.get_result();
}
waypt_nameposn_out_hash.clear();
void
GdbFormat::write()
{
- if (gdb_opt_ver) {
- gdb_ver = xstrtoi(gdb_opt_ver, nullptr, 10);
- }
write_header();
reset_short_handle("WPT");
#include "garmin_tables.h" // for gt_waypt_classes_e
#include "gbfile.h" // for gbfile
#include "mkshort.h" // for MakeShort
-#include "option.h" // for OptionBool, OptionCString
+#include "option.h" // for OptionBool, OptionString
class GdbFormat : public Format
WptNamePosnHash waypt_nameposn_out_hash;
MakeShort* short_h{};
- OptionCString gdb_opt_category;
- OptionCString gdb_opt_ver;
+ OptionInt gdb_opt_category;
+ OptionInt gdb_opt_ver;
OptionBool gdb_opt_via;
OptionBool gdb_opt_roadbook;
- OptionCString gdb_opt_bitcategory;
+ OptionInt gdb_opt_bitcategory;
OptionBool gdb_opt_drop_hidden_wpt;
int waypt_flag{};
},
{
"bitscategory", &gdb_opt_bitcategory, "Bitmap of categories",
- nullptr, ARGTYPE_INT, "1", "65535", nullptr
+ nullptr, ARGTYPE_BASE_AUTO | ARGTYPE_INT, "1", "65535", nullptr
},
{
"ver", &gdb_opt_ver,
writer.writeAttribute(QStringLiteral("lon"), QString::number(waypointp->longitude, 'f'));
writer.writeEndElement();
- writer.writeTextElement(QStringLiteral("type"), deficon ? deficon.get() : waypointp->icon_descr);
+ writer.writeTextElement(QStringLiteral("type"), deficon ? deficon : waypointp->icon_descr);
if (waypointp->HasUrlLink()) {
writer.writeStartElement(QStringLiteral("link"));
#include "defs.h"
#include "format.h" // for Format
#include "geocache.h" // for Geocache, Geocache::container_t
-#include "option.h" // for OptionBool, OptionCString
+#include "option.h" // for OptionBool, OptionString
class GeoFormat : public Format
/* Data Members */
- OptionCString deficon;
+ OptionString deficon;
QVector<arglist_t> geo_args = {
{"deficon", &deficon, "Default icon name", nullptr, ARGTYPE_STRING, ARG_NOMINMAX, nullptr },
printf(MYNAME " rd_init()\n");
}
if (opt_dump_file) {
- dumpfile = gbfopen(opt_dump_file.get(), "wb", MYNAME);
+ dumpfile = gbfopen(opt_dump_file, "wb", MYNAME);
if (!dumpfile) {
- printf(MYNAME " rd_init() creating dumpfile %s FAILED continue anyway\n", qPrintable(opt_dump_file.get()));
+ printf(MYNAME " rd_init() creating dumpfile %s FAILED continue anyway\n", qPrintable(opt_dump_file));
} else {
if (global_opts.debug_level > 1) {
- printf(MYNAME " rd_init() creating dumpfile %s for writing binary copy of serial stream\n", qPrintable(opt_dump_file.get()));
+ printf(MYNAME " rd_init() creating dumpfile %s for writing binary copy of serial stream\n", qPrintable(opt_dump_file));
}
}
}
}
if (opt_timezone) {
- if (QTimeZone::isTimeZoneIdAvailable(opt_timezone.getba())) {
- timezn = new QTimeZone(opt_timezone.getba());
+ if (QTimeZone::isTimeZoneIdAvailable(opt_timezone.get().toUtf8())) {
+ timezn = new QTimeZone(opt_timezone.get().toUtf8());
} else {
list_timezones();
- fatal(MYNAME ": Requested time zone \"%s\" not available.\n", qPrintable(opt_timezone.get()));
+ fatal(MYNAME ": Requested time zone \"%s\" not available.\n", qPrintable(opt_timezone));
}
} else {
timezn = nullptr;
#include "defs.h"
#include "format.h" // for Format
#include "gbfile.h" // for gbfclose, gbfopen, gbfread, gbfwrite, gbfile
-#include "option.h" // for OptionCString, OptionBool
+#include "option.h" // for OptionString, OptionBool
class GlobalsatSportFormat : public Format
OptionBool showlist; // if true show a list instead of download tracks
- OptionCString opt_dump_file; // dump raw data to this file (optional)
+ OptionString opt_dump_file; // dump raw data to this file (optional)
OptionBool opt_input_dump_file; // if true input is from a dump-file instead of serial console
- OptionCString opt_timezone;
+ OptionString opt_timezone;
gbfile* dumpfile{nullptr}; // used for creating bin/RAW datadump files, useful for testing
gbfile* in_file{nullptr}; // used for reading from bin/RAW datadump files, useful for testing
QTimeZone* timezn{nullptr};
#include <cmath> // for lround
#include <cstdio> // for sscanf
#include <cstdint> // for uint16_t
-#include <cstring> // for strchr, strncpy
+#include <cstring> // for strchr
#include <optional> // for optional
#include <utility> // for as_const
mkshort_handle->set_whitespace_ok(false);
}
- mkshort_handle->set_length(xstrtoi(snlen, nullptr, 10));
+ mkshort_handle->set_length(snlen.get_result());
}
void
* available use it, otherwise use the default.
*/
- if (opt_gpxver != nullptr) {
+ if (opt_gpxver) {
gpx_write_version = QVersionNumber::fromString(opt_gpxver.get()).normalized();
} else if (!gpx_highest_version_read.isNull()) {
gpx_write_version = gpx_highest_version_read;
GpxFormat::write()
{
- elevation_precision = xstrtoi(opt_elevation_precision, nullptr, 10);
+ elevation_precision = opt_elevation_precision.get_result();
gpx_reset_short_handle();
auto gpx_waypt_pr_lambda = [this](const Waypoint* waypointp)->void {
#include "format.h" // for Format
#include "formspec.h" // for FormatSpecificData
#include "mkshort.h" // for MakeShort
-#include "option.h" // for OptionBool, OptionCString
+#include "option.h" // for OptionBool, OptionString
#include "src/core/file.h" // for File
#include "src/core/xmlstreamwriter.h" // for XmlStreamWriter
#include "src/core/xmltag.h" // for xml_tag
OptionBool opt_logpoint;
OptionBool opt_humminbirdext;
OptionBool opt_garminext;
- OptionCString opt_elevation_precision;
+ OptionInt opt_elevation_precision;
int logpoint_ct = 0;
int elevation_precision{};
const QVersionNumber gpx_1_0 = QVersionNumber(1,0).normalized();
const QVersionNumber gpx_1_1 = QVersionNumber(1,1).normalized();
QVersionNumber gpx_highest_version_read;
- OptionCString opt_gpxver;
+ OptionString opt_gpxver;
QVersionNumber gpx_write_version;
QXmlStreamAttributes gpx_namespace_attribute;
QString link_type;
- OptionCString snlen;
+ OptionInt snlen;
OptionBool suppresswhite;
- OptionCString urlbase;
+ OptionString urlbase;
route_head* trk_head{};
route_head* rte_head{};
const route_head* current_trk_head{}; // Output.
if (opt_sport) {
for (unsigned int i = 0; i < std::size(gtc_sportlist); i++) {
- if (0 == case_ignore_strncmp(opt_sport.get(), gtc_sportlist[i], 2)) {
+ if (0 == case_ignore_strncmp(opt_sport, gtc_sportlist[i], 2)) {
gtc_sport = i;
break;
}
#include "defs.h" // for arglist_t, ff_cap, route_head, Waypoint, computed_trkdata, ARG_NOMINMAX, ff_cap_read, ARGTYPE_BOOL, ARGTYPE_STRING, ff_cap_none, ff_cap_write, ff_type, ff_type_file
#include "format.h" // for Format
#include "gbfile.h" // for gbfile
-#include "option.h" // for OptionBool, OptionCString
+#include "option.h" // for OptionBool, OptionString
#include "src/core/datetime.h" // for DateTime
#include "xmlgeneric.h" // for cb_cdata, xg_functor_map_entry, cb_start, cb_end
double gtc_end_lat{};
double gtc_end_long{};
- OptionCString opt_sport;
+ OptionString opt_sport;
OptionBool opt_course;
QVector<arglist_t> gtc_args = {
auto* waypointp = const_cast<Waypoint*>(wpt);
if (waypointp->altitude != unknown_alt) {
- if (addopt != nullptr) {
+ if (addopt) {
waypointp->altitude += addf;
}
void HeightFilter::init()
{
addf = 0.0;
- if (addopt != nullptr) {
+ if (addopt) {
if (parse_distance(addopt, &addf, 1.0, MYNAME) == 0) {
fatal(MYNAME ": No height specified with add option.");
}
#include "defs.h" // for arglist_t, ARG_NOMINMAX, ARGTYPE_BEGIN_REQ, ARGTYPE_BOOL, ARGTYPE_END_REQ, ARGTYPE_FLOAT, Waypoint
#include "filter.h" // for Filter
-#include "option.h" // for OptionBool, OptionCString
+#include "option.h" // for OptionBool, OptionString
#if FILTERS_ENABLED
void process() override;
private:
- OptionCString addopt;
+ OptionDouble addopt;
OptionBool wgs84tomslopt;
double addf{};
// include static constexpr data member definitions with intializers for grid as private members.
QVector<arglist_t> args = {
{
"add", &addopt, "Adds a constant value to every altitude",
- nullptr, ARGTYPE_BEGIN_REQ | ARGTYPE_FLOAT, ARG_NOMINMAX, nullptr
+ nullptr, ARGTYPE_ALLOW_TRAILING_DATA | ARGTYPE_BEGIN_REQ | ARGTYPE_STRING, ARG_NOMINMAX, nullptr
},
{
"wgs84tomsl", &wgs84tomslopt, "Converts WGS84 ellipsoidal height to orthometric height (MSL)",
#include <QChar> // for QChar
#include <QIODevice> // for QIODevice, QIODevice::WriteOnly
+#include <QRegularExpression> // for QRegularExpression
+#include <QRegularExpressionMatch> // for QRegularExpressionMatch
#include <QString> // for QString, operator!=
#include <QTextStream> // for QTextStream
#include <Qt> // for CaseInsensitive
file_out = new gpsbabel::TextStream;
file_out->open(fname, QIODevice::WriteOnly, MYNAME);
mkshort_handle = new MakeShort;
+
+ static const QRegularExpression re("^(?:ddd|dmm|dms)$");
+ assert(re.isValid());
+ if (re.match(opt_degformat).hasMatch()) {
+ degformat = opt_degformat.get().at(2).toLatin1();
+ } else {
+ fatal(MYNAME ": Unrecognized degformat %s, expected 'ddd', 'dmm' or 'dms'.\n", qPrintable(opt_degformat));
+ }
+
+ if (opt_altunits.get().startsWith('f')) {
+ altunits = 'f';
+ } else if (opt_altunits.get().startsWith('m')) {
+ altunits = 'm';
+ } else {
+ fatal(MYNAME ": Unrecognized altunits %s, expected 'f' for feet or 'm' for meters.\n", qPrintable(opt_altunits));
+ }
+
}
void
*file_out << " <td>\n";
*file_out << " <p class=\"gpsbabelwaypoint\">" << sn << " - ";
*file_out << QStringLiteral("%1 (%2%3 %4 %5)")
- .arg(pretty_deg_format(wpt->latitude, wpt->longitude, degformat[2], " ", true))
+ .arg(pretty_deg_format(wpt->latitude, wpt->longitude, degformat, " ", true))
.arg(utmz)
.arg(utmzc)
.arg(utme, 6, 'f', 0)
.arg(utmn, 7, 'f', 0);
if (wpt->altitude != unknown_alt) {
*file_out << QStringLiteral(" alt:%1")
- .arg((int)((altunits[0]=='f') ? METERS_TO_FEET(wpt->altitude) : wpt->altitude));
+ .arg((int)((altunits == 'f') ? METERS_TO_FEET(wpt->altitude) : wpt->altitude));
}
*file_out << "<br>\n";
if (wpt->description != wpt->shortname) {
double lat = logpart->xml_attribute("lat").toDouble();
double lon = logpart->xml_attribute("lon").toDouble();
*file_out << "<span class=\"gpsbabellogcoords\">"
- << pretty_deg_format(lat, lon, degformat[2], " ", true) << "</span><br>\n";
+ << pretty_deg_format(lat, lon, degformat, " ", true) << "</span><br>\n";
}
logpart = curlog->xml_findfirst(u"groundspeak:text");
<< gpsbabel_version << "\">\n";
}
*file_out << " <title>GPSBabel HTML Output</title>\n";
- if (stylesheet) {
+ if (opt_stylesheet) {
*file_out << R"( <link rel="stylesheet" type="text/css" href=")"
- << stylesheet << "\">\n";
+ << opt_stylesheet.get() << "\">\n";
} else {
*file_out << " <style>\n";
*file_out << " p.gpsbabelwaypoint { font-size: 120%; font-weight: bold }\n";
#include "defs.h"
#include "format.h" // for Format
#include "mkshort.h" // for MakeShort
-#include "option.h" // for OptionCString, OptionBool
+#include "option.h" // for OptionString, OptionBool
#include "src/core/textstream.h" // for TextStream
int waypoint_number{};
- OptionCString stylesheet;
+ OptionString opt_stylesheet;
OptionBool html_encrypt;
OptionBool includelogs;
- OptionCString degformat;
- OptionCString altunits;
+ OptionString opt_degformat;
+ OptionString opt_altunits;
+ char degformat{};
+ char altunits {};
QVector<arglist_t> html_args = {
{
- "stylesheet", &stylesheet,
+ "stylesheet", &opt_stylesheet,
"Path to HTML style sheet", nullptr, ARGTYPE_STRING, ARG_NOMINMAX, nullptr
},
{
"Include groundspeak logs if present", nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr
},
{
- "degformat", °format,
+ "degformat", &opt_degformat,
"Degrees output as 'ddd', 'dmm'(default) or 'dms'", "dmm", ARGTYPE_STRING, ARG_NOMINMAX, nullptr
},
{
- "altunits", &altunits,
+ "altunits", &opt_altunits,
"Units for altitude (f)eet or (m)etres", "m", ARGTYPE_STRING, ARG_NOMINMAX, nullptr
},
};
// If both found, attempt to merge them
if (pres_track && gnss_track) {
if (timeadj) {
- if (strcmp(timeadj, "auto") == 0) {
+ if (timeadj.get() == "auto") {
time_adj = correlate_tracks(pres_track, gnss_track);
- } else if (sscanf(timeadj, "%d", &time_adj) != 1) {
- fatal(MYNAME ": bad timeadj argument '%s'\n", qPrintable(timeadj.get()));
+ } else {
+ time_adj = timeadj.toInt();
}
} else {
time_adj = 0;
#include "formspec.h" // for FormatSpecificData, kFsIGC
#include "gbfile.h" // for gbfprintf, gbfclose, gbfopen, gbfputs, gbfgetstr, gbfile
#include "kml.h" // for wp_field
-#include "option.h" // for OptionBool, OptionCString
+#include "option.h" // for OptionBool, OptionString
#include "src/core/datetime.h" // for DateTime
/*
gbfile* file_out{};
char manufacturer[4] {};
const route_head* head{};
- OptionCString timeadj;
+ OptionString timeadj;
QVector<arglist_t> igc_args = {
{
#include <climits> // for INT_MAX
#include <cmath> // for ceil, isfinite
-#include <cstdlib> // for abs, strtod
+#include <cstdlib> // for abs
#include <optional> // for optional
#include <QString> // for QString
// How many points need to be inserted?
double npts = 0;
- if (opt_time != nullptr) {
+ if (opt_time) {
if (!timespan.has_value()) {
fatal(FatalMsg() << MYNAME ": points must have valid times to interpolate by time!");
}
// interpolate even if time is running backwards.
npts = std::abs(*timespan) / max_time_step;
- } else if (opt_dist != nullptr) {
+ } else if (opt_dist) {
double distspan = radtometers(gcdist(pos1, wpt->position()));
npts = distspan / max_dist_step;
}
void InterpolateFilter::init()
{
- if ((opt_time != nullptr) && (opt_dist != nullptr)) {
+ if (opt_time && opt_dist) {
fatal(FatalMsg() << MYNAME ": Can't interpolate on both time and distance.");
- } else if ((opt_time != nullptr) && opt_route) {
+ } else if (opt_time && opt_route) {
fatal(FatalMsg() << MYNAME ": Can't interpolate routes on time.");
- } else if (opt_time != nullptr) {
- max_time_step = 1000 * strtod(opt_time, nullptr); // milliseconds
+ } else if (opt_time) {
+ max_time_step = 1000 * opt_time.get_result(); // milliseconds
if (max_time_step <= 0) {
fatal(FatalMsg() << MYNAME ": interpolation time should be positive!");
}
- } else if (opt_dist != nullptr) {
+ } else if (opt_dist) {
if (parse_distance(opt_dist, &max_dist_step, kMetersPerMile, MYNAME) == 0) {
fatal(FatalMsg() << MYNAME ": no distance specified with distance option!");
}
#include "defs.h" // for ARG_NOMINMAX, arglist_t, ARGTYPE_BEGIN_EXCL, ARG...
#include "filter.h" // for Filter
-#include "option.h" // for OptionCString, OptionBool
+#include "option.h" // for OptionString, OptionBool
#if FILTERS_ENABLED
/* Data Members */
- OptionCString opt_time;
+ OptionDouble opt_time;
double max_time_step{0};
- OptionCString opt_dist;
+ OptionDouble opt_dist;
double max_dist_step{0};
OptionBool opt_route;
},
{
"distance", &opt_dist, "Distance interval",
- nullptr, ARGTYPE_END_EXCL | ARGTYPE_END_REQ | ARGTYPE_STRING,
+ nullptr, ARGTYPE_END_EXCL | ARGTYPE_END_REQ | ARGTYPE_ALLOW_TRAILING_DATA | ARGTYPE_STRING,
ARG_NOMINMAX, nullptr
},
{
#include "kml.h"
-#include <cctype> // for tolower, toupper
#include <cmath> // for fabs
#include <cstdio> // for sscanf, printf
-#include <cstdlib> // for strtod
-#include <cstring> // for strcmp
#include <optional> // for optional
#include <tuple> // for tuple, make_tuple
void KmlFormat::kml_init_color_sequencer(int steps_per_rev)
{
- if (rotate_colors) {
- float color_step = strtod(opt_rotate_colors, nullptr);
+ if (opt_rotate_colors) {
+ float color_step = opt_rotate_colors.get_result();
if (color_step > 0.0f) {
// step around circle by given number of degrees for each track(route)
kml_color_sequencer.step = static_cast<float>(kml_color_limit) * 6.0f * color_step / 360.0f;
void KmlFormat::wr_init(const QString& fname)
{
- char u = 's';
waypt_init_bounds(&kml_bounds);
kml_time_min = gpsbabel::DateTime();
kml_time_max = gpsbabel::DateTime();
- if (opt_units) {
- u = tolower(opt_units[0]);
- }
+ QChar u = opt_units.isEmpty()? 's' : opt_units.get().front().toLower();
unitsformatter = new UnitsFormatter();
- switch (u) {
- case 's':
+ switch (u.unicode()) {
+ case u's':
unitsformatter->setunits(UnitsFormatter::units_t::statute);
break;
- case 'm':
+ case u'm':
unitsformatter->setunits(UnitsFormatter::units_t::metric);
break;
- case 'n':
+ case u'n':
unitsformatter->setunits(UnitsFormatter::units_t::nautical);
break;
- case 'a':
+ case u'a':
unitsformatter->setunits(UnitsFormatter::units_t::aviation);
break;
default:
- fatal("Units argument '%s' should be 's' for statute units, 'm' for metric, 'n' for nautical or 'a' for aviation.\n", qPrintable(opt_units.get()));
+ fatal("Units argument '%s' should be 's' for statute units, 'm' for metric, 'n' for nautical or 'a' for aviation.\n", qPrintable(opt_units));
break;
}
/*
posnfilename = fname;
posnfilenametmp = QStringLiteral("%1-").arg(fname);
realtime_positioning = true;
- max_position_points = xstrtoi(opt_max_position_points, nullptr, 10);
+ max_position_points = opt_max_position_points.get_result();
}
void KmlFormat::wr_deinit()
}
if (is_multitrack) {
- kml_output_linestyle(opt_line_color.get(),
+ kml_output_linestyle(opt_line_color,
highlighted ? line_width + 2 :
line_width);
}
writer->writeStartElement(QStringLiteral("Style"));
writer->writeStartElement(QStringLiteral("IconStyle"));
writer->writeStartElement(QStringLiteral("Icon"));
- writer->writeTextElement(QStringLiteral("href"), opt_deficon.get());
+ writer->writeTextElement(QStringLiteral("href"), opt_deficon);
writer->writeEndElement(); // Close Icon tag
writer->writeEndElement(); // Close IconStyle tag
writer->writeEndElement(); // Close Style tag
}
writer->writeStartElement(QStringLiteral("Placemark"));
writer->writeTextElement(QStringLiteral("name"), QStringLiteral("Path"));
- if (!rotate_colors) {
+ if (!opt_rotate_colors) {
writer->writeTextElement(QStringLiteral("styleUrl"), QStringLiteral("#lineStyle"));
}
- if (header->line_color.bbggrr >= 0 || header->line_width >= 0 || rotate_colors) {
+ if (header->line_color.bbggrr >= 0 || header->line_width >= 0 || opt_rotate_colors) {
writer->writeStartElement(QStringLiteral("Style"));
writer->writeStartElement(QStringLiteral("LineStyle"));
- if (rotate_colors) {
+ if (opt_rotate_colors) {
kml_step_color();
writer->writeTextElement(QStringLiteral("color"), QStringLiteral("%1%2")
.arg(kml_color_sequencer.color.opacity, 2, 16, QChar('0')).arg(kml_color_sequencer.color.bbggrr, 6, 16, QChar('0')));
- writer->writeTextElement(QStringLiteral("width"), opt_line_width.get());
+ writer->writeTextElement(QStringLiteral("width"), opt_line_width);
} else {
if (header->line_color.bbggrr >= 0) {
writer->writeTextElement(QStringLiteral("color"), QStringLiteral("%1%2")
kml_output_timestamp(waypointp);
// Icon - but only if it looks like a URL.
- icon = opt_deficon ? opt_deficon.get() : waypointp->icon_descr;
+ icon = opt_deficon ? opt_deficon : waypointp->icon_descr;
if (icon.contains("://")) {
writer->writeStartElement(QStringLiteral("Style"));
writer->writeStartElement(QStringLiteral("IconStyle"));
export_track = opt_export_track;
floating = opt_floating;
extrude = opt_extrude;
- rotate_colors = (!! opt_rotate_colors);
trackdata = opt_trackdata;
trackdirection = opt_trackdirection;
- line_width = xstrtoi(opt_line_width, nullptr, 10);
- precision = xstrtoi(opt_precision, nullptr, 10);
+ line_width = opt_line_width.get_result();
+ precision = opt_precision.get_result();
writer->writeStartDocument();
if (track_waypt_count() || route_waypt_count()) {
writer->writeStartElement(QStringLiteral("Style"));
writer->writeAttribute(QStringLiteral("id"), QStringLiteral("lineStyle"));
- kml_output_linestyle(opt_line_color.get(), line_width);
+ kml_output_linestyle(opt_line_color, line_width);
writer->writeEndElement(); // Close Style tag
}
#include "defs.h"
#include "format.h"
-#include "option.h" // for OptionBool, OptionCString
+#include "option.h" // for OptionBool, OptionString
#include "src/core/datetime.h" // for DateTime
#include "src/core/file.h" // for File
#include "src/core/xmlstreamwriter.h" // for XmlStreamWriter
QHash<const route_head*, track_trait_t> kml_track_traits_hash;
// options
- OptionCString opt_deficon;
+ OptionString opt_deficon;
OptionBool opt_export_lines;
OptionBool opt_export_points;
OptionBool opt_export_track;
- OptionCString opt_line_width;
- OptionCString opt_line_color;
+ OptionInt opt_line_width;
+ OptionString opt_line_color;
OptionBool opt_floating;
OptionBool opt_extrude;
OptionBool opt_trackdata;
OptionBool opt_trackdirection;
- OptionCString opt_units;
+ OptionString opt_units;
OptionBool opt_labels;
- OptionCString opt_max_position_points;
- OptionCString opt_rotate_colors;
- OptionCString opt_precision;
+ OptionInt opt_max_position_points;
+ OptionDouble opt_rotate_colors;
+ OptionInt opt_precision;
bool export_lines{};
bool export_points{};
bool trackdata{};
bool trackdirection{};
int max_position_points{};
- bool rotate_colors{};
int line_width{};
int precision{};
#include <cstdio> // for printf, sprintf, SEEK_CUR
#include <cstdint> // for int64_t
#include <cstdlib> // for abs
-#include <cstring> // for strcmp, strlen
#include <numbers> // for pi
#include <utility> // for as_const
file_out = gbfopen_le(fname, "wb", MYNAME);
mkshort_handle = new MakeShort;
waypt_out_count = 0;
- writing_version = xstrtoi(opt_wversion, nullptr, 10);
+ writing_version = opt_wversion.get_result();
if ((writing_version < 2) || (writing_version > 4)) {
- fatal(MYNAME " wversion value %s is not supported !!\n", qPrintable(opt_wversion.get()));
+ fatal(MYNAME " wversion value %s is not supported !!\n", qPrintable(opt_wversion));
}
utf16le_codec = QTextCodec::codecForName("UTF-16LE");
waypt_table = new QList<const Waypoint*>;
/* file title */
buf = opt_title.isEmpty()?
- QStringLiteral("GPSBabel generated USR data file") : opt_title.get();
+ QStringLiteral("GPSBabel generated USR data file") : opt_title;
if (global_opts.debug_level >= 1) {
printf(MYNAME " data_write: Title = '%s'\n", qPrintable(buf));
}
gbfputc(0, file_out);
/* device serial number */
- opt_serialnum_i = xstrtoi(opt_serialnum, nullptr, 10);
+ opt_serialnum_i = opt_serialnum.get_result();
gbfputint32(opt_serialnum_i, file_out);
/* content description */
buf = opt_content_descr.isEmpty()?
- QStringLiteral("Waypoints, routes, and trails") : opt_content_descr.get();
+ QStringLiteral("Waypoints, routes, and trails") : opt_content_descr;
if (global_opts.debug_level >= 1) {
printf(MYNAME " data_write: Description = '%s'\n", qPrintable(buf));
}
#include "formspec.h" // for FsChainFind, FsChainAdd, kFsLowranceusr4, FormatSpecificData
#include "gbfile.h" // for gbfgetint32, gbfputint32, gbfputint16, gbfgetc, gbfgetint16, gbfwrite, gbfputc, gbfeof, gbfgetflt, gbfclose, gbfgetdbl, gbfopen_le, gbfputdbl, gbfputs, gbfile, gbfputflt, gbfread, gbfseek
#include "mkshort.h" // for MakeShort
-#include "option.h" // for OptionBool, OptionCString
+#include "option.h" // for OptionBool, OptionString
#include "src/core/datetime.h" // for DateTime
OptionBool opt_ignoreicons;
OptionBool opt_writeasicons;
OptionBool opt_seg_break;
- OptionCString opt_wversion;
- OptionCString opt_title;
- OptionCString opt_content_descr;
- OptionCString opt_serialnum;
+ OptionInt opt_wversion;
+ OptionString opt_title;
+ OptionString opt_content_descr;
+ OptionInt opt_serialnum;
int opt_serialnum_i{};
QList<const Waypoint*>* waypt_table{nullptr};
#include "mtk_logger.h"
+#include <algorithm> // for clamp
#include <cctype> // for isdigit
#include <cstdarg> // for va_end, va_start
#include <cstring> // for memcmp, memset, strncmp, strlen, memmove, strchr, strcpy, strerror, strstr
#include <QStringLiteral> // for qMakeStringPrivate, QStringLiteral
#include <QThread> // for QThread
#include <QtCore> // for qPrintable, UTC
-#include <cerrno> // for errno, ERANGE
+#include <cerrno> // for errno
#include <cmath> // for fabs
-#include <cstdlib> // for strtoul, strtol
+#include <cstdlib> // for strtoul
#include "defs.h"
#include "gbfile.h" // for gbfprintf, gbfputc, gbfputs, gbfclose, gbfopen, gbfile
unsigned int scan_step = 0x10000;
unsigned int scan_bsize = 0x0400;
- unsigned int read_bsize_kb = strtol(OPT_block_size_kb, nullptr, 10);
- if (errno == ERANGE || read_bsize_kb < 1) {
- read_bsize_kb = 1;
- } else if (read_bsize_kb > 64) {
- read_bsize_kb = 64;
- }
+ unsigned int read_bsize_kb = std::clamp(OPT_block_size_kb.get_result(), 1, 64);
unsigned int read_bsize = read_bsize_kb * 1024;
dbg(2, "Download block size is %d bytes\n", read_bsize);
if (init_scan) {
/********************** MTK Logger -- CSV output *************************/
-void MtkLoggerBase::mtk_csv_init(const char* csv_fname, unsigned long bitmask)
+void MtkLoggerBase::mtk_csv_init(const QString& csv_fname, unsigned long bitmask)
{
FILE* cf;
- dbg(1, "Opening csv output file %s...\n", csv_fname);
+ dbg(1, "Opening csv output file %s...\n", qPrintable(csv_fname));
// can't use gbfopen here - it will fatal() if file doesn't exist
- if ((cf = ufopen(QString::fromUtf8(csv_fname), "r")) != nullptr) {
+ if ((cf = ufopen(csv_fname, "r")) != nullptr) {
fclose(cf);
- warning(MYNAME ": CSV file %s already exist ! Cowardly refusing to overwrite.\n", csv_fname);
+ warning(MYNAME ": CSV file %s already exist ! Cowardly refusing to overwrite.\n", qPrintable(csv_fname));
return;
}
if ((cd = gbfopen(csv_fname, "w", MYNAME)) == nullptr) {
- fatal(MYNAME ": Can't open csv file '%s'\n", csv_fname);
+ fatal(MYNAME ": Can't open csv file '%s'\n", qPrintable(csv_fname));
}
/* Add the header line */
mtk_info.logLen = mtk_log_len(mtk_info.bitmask);
dbg(3, "Log item size %d bytes\n", mtk_info.logLen);
- if (csv_file && *csv_file) {
- mtk_csv_init(static_cast<const char*>(csv_file), mtk_info.bitmask);
+ if (!csv_file.isEmpty()) {
+ mtk_csv_init(csv_file, mtk_info.bitmask);
}
while (pos < fsize && (bLen = fread(&buf[j], 1, sizeof(buf)-j, fl)) > 0) {
#include "defs.h"
#include "format.h" // for Format
#include "gbfile.h" // for gbfile
-#include "option.h" // for OptionBool, OptionCString
+#include "option.h" // for OptionBool, OptionString
class MtkLoggerBase
OptionBool OPT_erase; /* erase ? command option */
OptionBool OPT_erase_only; /* erase_only ? command option */
OptionBool OPT_log_enable; /* enable ? command option */
- OptionCString csv_file; /* csv ? command option */
- OptionCString OPT_block_size_kb; /* block_size_kb ? command option */
+ OptionString csv_file; /* csv ? command option */
+ OptionInt OPT_block_size_kb; /* block_size_kb ? command option */
MTK_DEVICE_TYPE mtk_device = MTK_LOGGER;
mtk_loginfo mtk_info{};
int mtk_erase();
void mtk_read();
int add_trackpoint(int idx, long unsigned int bmask, data_item* itm);
- void mtk_csv_init(const char* csv_fname, long unsigned int bitmask);
+ void mtk_csv_init(const QString& csv_fname, long unsigned int bitmask);
void mtk_csv_deinit();
static int csv_line(gbfile* csvFile, int idx, long unsigned int bmask, data_item* itm);
int mtk_parse(unsigned char* data, int dataLen, unsigned int bmask);
#include <cctype> // for isprint
#include <cmath> // for fabs
#include <cstdio> // for snprintf, sscanf, fprintf, fputc, stderr
-#include <cstdlib> // for strtod
#include <cstring> // for strncmp, strchr, strlen, strstr, memset, strrchr
#include <iterator> // for operator!=, reverse_iterator
sleepms = -1;
if (opt_sleep) {
- if (*opt_sleep) {
- sleepms = 1e3 * strtod(opt_sleep, nullptr);
+ if (!opt_sleep.isEmpty()) {
+ sleepms = 1e3 * opt_sleep.get_result();
} else {
sleepms = -1;
}
}
mkshort_handle = new MakeShort;
- mkshort_handle->set_length(xstrtoi(snlenopt, nullptr, 10));
+ mkshort_handle->set_length(snlenopt.get_result());
if (opt_gisteq) {
opt_gpgga.reset();
}
if (!prev_datetime.date().isValid()) {
- if (optdate == nullptr) {
+ if (!optdate) {
warning(MYNAME ": No date found within track (all points dropped)!\n");
warning(MYNAME ": Please use option \"date\" to preset a valid date for those tracks.\n");
track_del_head(track);
}
if (optdate) {
- opt_tm = QDate::fromString(optdate.get(), u"yyyyMMdd");
+ opt_tm = QDate::fromString(optdate, u"yyyyMMdd");
if (!opt_tm.isValid()) {
- fatal(MYNAME ": Invalid date \"%s\"!\n", qPrintable(optdate.get()));
+ fatal(MYNAME ": Invalid date \"%s\"!\n", qPrintable(optdate));
}
}
gbser_flush(gbser_handle);
if (opt_baud) {
- if (!gbser_set_speed(gbser_handle, xstrtoi(opt_baud, nullptr, 10))) {
- fatal(MYNAME ": Unable to set baud rate %s\n", qPrintable(opt_baud.get()));
+ if (!gbser_set_speed(gbser_handle, opt_baud.get_result())) {
+ fatal(MYNAME ": Unable to set baud rate %s\n", qPrintable(opt_baud));
}
}
posn_fname = fname;
#include "format.h" // for Format
#include "gbfile.h" // for gbfile
#include "mkshort.h" // for MakeShort
-#include "option.h" // for OptionBool, OptionCString
+#include "option.h" // for OptionBool, OptionString
class NmeaFormat : public Format
OptionBool opt_gpgga;
OptionBool opt_gpvtg;
OptionBool opt_gpgsa;
- OptionCString snlenopt;
- OptionCString optdate;
+ OptionInt snlenopt;
+ OptionInt optdate;
OptionBool getposnarg;
- OptionCString opt_sleep;
- OptionCString opt_baud;
+ OptionInt opt_sleep;
+ OptionInt opt_baud;
OptionBool opt_append;
OptionBool opt_gisteq;
OptionBool opt_ignorefix;
- long sleepms{};
+ int sleepms{};
int getposn{};
bool amod_waypoint{};
--- /dev/null
+/*
+ Copyright (C) 2024 Robert Lipe, robertlipe+source@gpsbabel.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ */
+#include "option.h"
+
+#include <QString> // for QString
+
+#include "defs.h" // for parse_double, parse_integer
+
+
+int OptionString::toInt() const
+{
+ return parse_integer(value_, id_);
+}
+
+int OptionString::toInt(bool* ok) const
+{
+ return parse_integer(value_, id_, ok);
+}
+
+int OptionString::toInt(bool* ok, QString* end, int base) const
+{
+ return parse_integer(value_, id_, ok, end, base);
+}
+
+double OptionString::toDouble() const
+{
+ return parse_double(value_, id_);
+}
+
+double OptionString::toDouble(bool* ok) const
+{
+ return parse_double(value_, id_, ok);
+}
+
+double OptionString::toDouble(bool* ok, QString* end) const
+{
+ return parse_double(value_, id_, ok, end);
+}
class Option /* Abstract Class */
{
public:
- /* Types */
- enum option_t {
- type_cstring,
- type_boolean,
- };
-
/* Special Member Functions */
Option() = default;
// Provide virtual public destructor to avoid undefined behavior when
Option& operator=(Option&&) = delete;
/* Member Functions */
- [[nodiscard]] virtual option_t type() const = 0;
[[nodiscard]] virtual bool has_value() const = 0;
virtual void reset() = 0;
[[nodiscard]] virtual bool isEmpty() const = 0;
[[nodiscard]] virtual const QString& get() const = 0;
virtual void set(const QString& s) = 0;
+ virtual void set_id(const QString& id)
+ {
+ }
/* Data Members */
// I.25: Prefer empty abstract classes as interfaces to class hierarchies
// https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#i25-prefer-empty-abstract-classes-as-interfaces-to-class-hierarchies
};
-class OptionCString : public Option
+class [[deprecated]] OptionCString : public Option
{
public:
/* Special Member Functions */
return value_.isNull()? nullptr : valueb_.constData();
}
- [[nodiscard]] option_t type() const override
- {
- return type_cstring;
- }
-
[[nodiscard]] bool has_value() const override
{
return !value_.isNull();
QByteArray valueb_;
};
+class OptionString : public Option
+{
+public:
+ /* Special Member Functions */
+ OptionString() = default;
+
+ explicit(false) operator const QString& () const
+ {
+ return value_;
+ }
+
+ explicit(false) operator bool () const
+ {
+ return !value_.isNull();
+ }
+
+ [[nodiscard]] bool has_value() const override
+ {
+ return !value_.isNull();
+ }
+
+ void reset() override
+ {
+ value_ = QString();
+ }
+
+ [[nodiscard]] bool isEmpty() const override
+ {
+ return value_.isEmpty();
+ }
+
+ [[nodiscard]] const QString& get() const override
+ {
+ return value_;
+ }
+
+ void set(const QString& s) override
+ {
+ value_ = s;
+ }
+
+ void set_id(const QString& id) override
+ {
+ id_ = id;
+ }
+
+// We use overloads instead of default parameters to enable tool visibility into different usages.
+ int toInt() const;
+ int toInt(bool* ok) const;
+ int toInt(bool* ok, QString* end, int base) const;
+ double toDouble() const;
+ double toDouble(bool* ok) const;
+ double toDouble(bool* ok, QString* end) const;
+
+private:
+ QString value_;
+ QString id_;
+};
+
+class OptionInt : public Option
+{
+public:
+ /* Special Member Functions */
+ OptionInt() = default;
+
+ explicit(false) operator const QString& () const
+ {
+ return value_;
+ }
+
+ explicit(false) operator bool () const
+ {
+ return !value_.isNull();
+ }
+
+ [[nodiscard]] bool has_value() const override
+ {
+ return !value_.isNull();
+ }
+
+ void reset() override
+ {
+ value_ = QString();
+ result_ = 0;
+ end_ = QString();
+ }
+
+ [[nodiscard]] bool isEmpty() const override
+ {
+ return value_.isEmpty();
+ }
+
+ [[nodiscard]] const QString& get() const override
+ {
+ return value_;
+ }
+
+ void set(const QString& s) override
+ {
+ value_ = s;
+ }
+
+ void set_id(const QString& id) override
+ {
+ id_ = id;
+ }
+
+ void set_result(int result, const QString& end)
+ {
+ result_ = result;
+ end_ = end;
+ }
+
+ int get_result(QString* end = nullptr) const {
+ if (end != nullptr) {
+ *end = end_;
+ }
+ return result_;
+ }
+
+private:
+ QString value_;
+ QString id_;
+ int result_{};
+ QString end_;
+};
+
+class OptionDouble : public Option
+{
+public:
+ /* Special Member Functions */
+ OptionDouble() = default;
+
+ explicit(false) operator const QString& () const
+ {
+ return value_;
+ }
+
+ explicit(false) operator bool () const
+ {
+ return !value_.isNull();
+ }
+
+ [[nodiscard]] bool has_value() const override
+ {
+ return !value_.isNull();
+ }
+
+ void reset() override
+ {
+ value_ = QString();
+ result_ = 0.0;
+ end_ = QString();
+ }
+
+ [[nodiscard]] bool isEmpty() const override
+ {
+ return value_.isEmpty();
+ }
+
+ [[nodiscard]] const QString& get() const override
+ {
+ return value_;
+ }
+
+ void set(const QString& s) override
+ {
+ value_ = s;
+ }
+
+ void set_id(const QString& id) override
+ {
+ id_ = id;
+ }
+
+ void set_result(double result, const QString& end)
+ {
+ result_ = result;
+ end_ = end;
+ }
+
+ double get_result(QString* end = nullptr) const {
+ if (end != nullptr) {
+ *end = end_;
+ }
+ return result_;
+ }
+
+private:
+ QString value_;
+ QString id_;
+ double result_{};
+ QString end_;
+};
+
class OptionBool : public Option
{
public:
/* Special Member Functions */
OptionBool() = default;
- /* Traditionally unsupplied bool options without default are considered to be false. */
+ /* Traditionally un-supplied bool options without default are considered to be false. */
explicit(false) operator bool() const
{
return (!value_.isNull() && (value_ != '0'));
}
- [[nodiscard]] option_t type() const override
- {
- return type_boolean;
- }
-
/* Note that has_value can be used to distinguish an option that wasn't supplied
* from one that was supplied and is considered false by Vecs::assign_option.
*/
break;
}
- if (QString creator = created_by.get(); !creator.isEmpty()) {
+ if (QString creator = created_by; !creator.isEmpty()) {
if (!gpsbabel_testmode()) {
if (creator == "GPSBabel") {
creator += '-';
osm_disp_feature(waypoint);
}
- osm_write_opt_tag(opt_tagnd.get());
+ osm_write_opt_tag(opt_tagnd);
fout->writeEndElement(); // node
}
return;
}
- if (QString creator = created_by.get(); !creator.isEmpty()) {
+ if (QString creator = created_by; !creator.isEmpty()) {
if (!gpsbabel_testmode()) {
if (creator == "GPSBabel") {
creator += '-';
osm_write_tag("name", route->rte_name);
osm_write_tag("note", route->rte_desc);
- osm_write_opt_tag(opt_tag.get());
+ osm_write_opt_tag(opt_tag);
fout->writeEndElement(); // way
}
#include "defs.h"
#include "format.h" // for Format
-#include "option.h" // for OptionCString
+#include "option.h" // for OptionString
#include "src/core/file.h" // for File
#include "src/core/xmlstreamwriter.h" // for XmlStreamWriter
#include "xmlgeneric.h" // for xg_functor_map_entry, cb_start, cb_end
/* Data Members */
- OptionCString opt_tag;
- OptionCString opt_tagnd;
- OptionCString created_by;
+ OptionString opt_tag;
+ OptionString opt_tagnd;
+ OptionString created_by;
QVector<arglist_t> osm_args = {
{ "tag", &opt_tag, "Write additional way tag key/value pairs", nullptr, ARGTYPE_STRING, ARG_NOMINMAX, nullptr},
#include "ozi.h"
-#include <cctype> // for tolower
#include <cmath> // for lround
#include <QByteArray> // for QByteArray
OziFormat::ozi_open_io(const QString& fname, QIODevice::OpenModeFlag mode)
{
stream = new gpsbabel::TextStream;
- stream->open(fname, mode, MYNAME, opt_codec);
+ stream->open(fname, mode, MYNAME, opt_codec.get().toUtf8());
if (mode & QFile::WriteOnly) {
stream->setRealNumberNotation(QTextStream::FixedNotation);
auto* fsdata = new ozi_fsdata;
/* Provide defaults via command line defaults */
- fsdata->fgcolor = color_to_bbggrr(wptfgcolor.get());
- fsdata->bgcolor = color_to_bbggrr(wptbgcolor.get());
+ fsdata->fgcolor = color_to_bbggrr(wptfgcolor);
+ fsdata->bgcolor = color_to_bbggrr(wptbgcolor);
return fsdata;
}
void
OziFormat::ozi_init_units(const int direction) /* 0 = in; 1 = out */
{
- altunit = tolower(*altunit_opt);
- switch (altunit) {
- case 'm': /* meters, okay */
- alt_scale = 1.0;
- break;
- case 'f': /* feet, okay */
- alt_scale = FEET_TO_METERS(1.0);
- break;
- default:
- fatal(MYNAME ": Unknown value (%s) for option 'altunit'!\n", qPrintable(altunit_opt.get()));
+ if (altunit_opt.get().startsWith('m', Qt::CaseInsensitive)) {
+ altunit = 'm';
+ alt_scale = 1.0; /* meters */
+ } else if (altunit_opt.get().startsWith('f', Qt::CaseInsensitive)) {
+ altunit = 'f';
+ alt_scale = FEET_TO_METERS(1.0); /* feet */
+ } else {
+ fatal(MYNAME ": Unknown value (%s) for option 'altunit'!\n", qPrintable(altunit_opt));
}
if (direction != 0) {
- alt_scale = 1 / alt_scale;
- }
-
- proxunit = tolower(*proxunit_opt);
- switch (proxunit) {
- case 'm': /* miles, okay */
- prox_scale = MILES_TO_METERS(1.0);
- break;
- case 'n': /* nautical miles, okay */
- prox_scale = NMILES_TO_METERS(1.0);
- break;
- case 'k': /* kilometers, okay */
- prox_scale = 1000.0;
- break;
- default:
- fatal(MYNAME ": Unknown value (%s) for option 'proxunit'!\n", qPrintable(proxunit_opt.get()));
+ alt_scale = 1.0 / alt_scale;
+ }
+
+ if (proxunit_opt.get().startsWith('m')) {
+ proxunit = 'm';
+ prox_scale = MILES_TO_METERS(1.0); /* miles */
+ } else if (proxunit_opt.get().startsWith('n')) {
+ proxunit = 'n';
+ prox_scale = NMILES_TO_METERS(1.0); /* nautical miles */
+ } else if (proxunit_opt.get().startsWith('k')) {
+ proxunit = 'k';
+ prox_scale = 1000.0; /* kilometers */
+ } else {
+ fatal(MYNAME ": Unknown value (%s) for option 'proxunit'!\n", qPrintable(proxunit_opt));
}
if (direction != 0) {
- prox_scale = 1 / prox_scale;
+ prox_scale = 1.0 / prox_scale;
}
}
/* set mkshort options from the command line if applicable */
if (global_opts.synthesize_shortnames) {
- mkshort_handle->set_length(xstrtoi(snlenopt, nullptr, 10));
+ mkshort_handle->set_length(snlenopt.get_result());
if (snwhiteopt.has_value()) {
mkshort_handle->set_whitespace_ok(snwhiteopt);
}
ozi_init_units(1);
- parse_distance(proximityarg, &proximity, 1 / prox_scale, MYNAME);
+ parse_distance(proximityarg, &proximity, 1.0 / prox_scale, MYNAME);
}
void
#include "format.h" // for Format
#include "formspec.h" // for FormatSpecificData, kFsOzi
#include "mkshort.h" // for MakeShort
-#include "option.h" // for OptionCString, OptionBool
+#include "option.h" // for OptionString, OptionBool
#include "src/core/textstream.h" // for TextStream
int route_wpt_count{};
int new_track{};
- OptionCString snlenopt;
+ OptionInt snlenopt;
OptionBool snwhiteopt;
OptionBool snupperopt;
OptionBool snuniqueopt;
- OptionCString wptfgcolor;
- OptionCString wptbgcolor;
+ OptionString wptfgcolor;
+ OptionString wptbgcolor;
OptionBool pack_opt;
int datum{};
- OptionCString proximityarg;
+ OptionDouble proximityarg;
double proximity{};
- OptionCString altunit_opt;
- OptionCString proxunit_opt;
+ OptionString altunit_opt;
+ OptionString proxunit_opt;
char altunit{};
char proxunit{};
double alt_scale{};
double prox_scale{};
- OptionCString opt_codec;
+ OptionString opt_codec;
QVector<arglist_t> ozi_args = {
{
},
{
"proximity", &proximityarg, "Proximity distance",
- "0", ARGTYPE_STRING, ARG_NOMINMAX, nullptr
+ "0", ARGTYPE_ALLOW_TRAILING_DATA | ARGTYPE_STRING, ARG_NOMINMAX, nullptr
},
{
"altunit", &altunit_opt, "Unit used in altitude values",
*/
-#include <cctype> // for isspace
-#include <cmath> // for fabs
-#include <cstdio> // for sscanf
-#include <cstdlib> // for strtod
+#include <cmath> // for fabs
+#include <cstdio> // for sscanf
+#include <stdexcept> // for invalid_argument, out_of_range
+#include <string> // for stod
-#include <QString> // for QString
+#include <QString> // for QString
+#include <QtGlobal> // for qPrintable
-#include "defs.h" // for case_ignore_strcmp, fatal, KPH_TO_MPS, MPH_TO_MPS, warning, FEET_TO_METERS, KNOTS_TO_MPS, CSTR, FATHOMS_TO_METERS, MILES_TO_METERS, NMILES_TO_METERS, kDatumWGS84, grid_type, parse_coordinates, parse_distance, parse_speed, grid_bng, grid_lat_lon_ddd, grid_lat_lo...
-#include "jeeps/gpsmath.h" // for GPS_Math_Known_Datum_To_WGS84_M, GPS_Math_Swiss_EN_To_WGS84, GPS_Math_UKOSMap_To_WGS84_H, GPS_Math_UTM_EN_To_Known_Datum
+#include "defs.h" // for case_ignore_strcmp, fatal, grid_type, KPH_TO_MPS, MPH_TO_MPS, warning, FEET_TO_METERS, KNOTS_TO_MPS, kDatumWGS84, FATHOMS_TO_METERS, MILES_TO_METERS, NMILES_TO_METERS, parse_coordinates, CSTR, parse_distance, parse_double, parse_integer, parse_speed
+#include "jeeps/gpsmath.h" // for GPS_Math_Known_Datum_To_WGS84_M, GPS_Math_Swiss_EN_To_WGS84, GPS_Math_UKOSMap_To_WGS84_H, GPS_Math_UTM_EN_To_Known_Datum
+
+
+/*
+ * parse_integer
+ *
+ * str: input string
+ * id: identifier for error messages
+ * ok: conversion status.
+ * if nullptr any conversion errors will fatal.
+ * end: unconverted trailing portion of string.
+ * if nullptr a non-empty trailing portion will cause a conversion error.
+ * base: conversion base
+ */
+
+int parse_integer(const QString& str, const QString& id, bool* ok, QString* end, int base)
+{
+ auto ss = str.toStdString();
+ size_t pos = 0;
+ int result = 0;
+ try {
+ result = stoi(ss, &pos, base);
+ } catch (const std::invalid_argument&) {
+ if (ok == nullptr) {
+ fatal("%s: conversion to integer failed: invalid argument \"%s\".\n",
+ qPrintable(id), qPrintable(str));
+ } else {
+ *ok = false;
+ return 0;
+ }
+ } catch (const std::out_of_range&) {
+ if (ok == nullptr) {
+ fatal("%s: conversion to integer failed: out of range \"%s\".\n",
+ qPrintable(id), qPrintable(str));
+ } else {
+ *ok = false;
+ return 0;
+ }
+ } catch (...) {
+ if (ok == nullptr) {
+ fatal("%s: conversion to integer failed: unknown exception \"%s\".\n",
+ qPrintable(id), qPrintable(str));
+ } else {
+ *ok = false;
+ return 0;
+ }
+ }
+
+ QString remainder = QString::fromStdString(ss.erase(0, pos));
+ if ((end == nullptr) && !remainder.trimmed().isEmpty()) {
+ if (ok == nullptr) {
+ fatal("%s: conversion to integer failed: conversion of \"%s\" failed due to unexpected trailing data \"%s\".\n",
+ qPrintable(id), qPrintable(str), qPrintable(remainder));
+ } else {
+ *ok = false;
+ return 0;
+ }
+ }
+ if (end != nullptr) { // return possibly empty trailing portion of str
+ *end = remainder;
+ }
+
+ if (ok != nullptr) {
+ *ok = true;
+ }
+
+ return result;
+}
+
+/*
+ * parse_double
+ *
+ * str: input string
+ * id: identifier for error messages
+ * ok: conversion status.
+ * if nullptr any conversion errors will fatal.
+ * end: unconverted trailing portion of string.
+ * if nullptr a non-empty trailing portion will cause a conversion error.
+ * base: conversion base
+ *
+ */
+
+double parse_double(const QString& str, const QString& id, bool* ok, QString* end)
+{
+ auto ss = str.toStdString();
+ size_t pos = 0;
+ double result = 0.0;
+ try {
+ result = stod(ss, &pos);
+ } catch (const std::invalid_argument&) {
+ if (ok == nullptr) {
+ fatal("%s: conversion to double failed: invalid argument \"%s\".\n",
+ qPrintable(id), qPrintable(str));
+ } else {
+ *ok = false;
+ return 0.0;
+ }
+ } catch (const std::out_of_range&) {
+ if (ok == nullptr) {
+ fatal("%s: conversion to double failed: out of range \"%s\".\n",
+ qPrintable(id), qPrintable(str));
+ } else {
+ *ok = false;
+ return 0.0;
+ }
+ } catch (...) {
+ if (ok == nullptr) {
+ fatal("%s: conversion to double failed: unknown exception \"%s\".\n",
+ qPrintable(id), qPrintable(str));
+ } else {
+ *ok = false;
+ return 0.0;
+ }
+ }
+
+ QString remainder = QString::fromStdString(ss.erase(0, pos));
+ if ((end == nullptr) && !remainder.trimmed().isEmpty()) {
+ if (ok == nullptr) {
+ fatal("%s: conversion to double failed: conversion of \"%s\" failed due to unexpected trailing data \"%s\".\n",
+ qPrintable(id), qPrintable(str), qPrintable(remainder));
+ } else {
+ *ok = false;
+ return 0.0;
+ }
+ }
+ if (end != nullptr) { // return possibly empty trailing portion of str
+ *end = remainder;
+ }
+
+ if (ok != nullptr) {
+ *ok = true;
+ }
+
+ return result;
+}
/*
* parse_distance:
*/
int
-parse_distance(const char* str, double* val, double scale, const char* module)
+parse_distance(const QString& str, double* val, double scale, const char* module)
{
- char* unit;
-
- if ((str == nullptr) || (*str == '\0')) {
+ if (str.isEmpty()) {
return 0;
}
- *val = strtod(str, &unit);
- if (unit == nullptr) {
- fatal("%s: Unconvertible numeric value (%s)!\n", module, str);
- }
+
+ QString unit;
+ constexpr bool* dieonfailure = nullptr;
+ *val = parse_double(str, module, dieonfailure, &unit);
if (fabs(*val) + 1 >= 1.0e25) {
return 0; /* not only Garmin uses this as 'unknown value' */
}
- while (isspace(*unit)) {
- unit++;
- }
+ unit = unit.trimmed();
- if (*unit == '\0') {
+ if (unit.isEmpty()) {
*val *= scale;
return 1;
}
} else if (case_ignore_strcmp(unit, "fa") == 0) {
*val = FATHOMS_TO_METERS(*val);
} else {
- fatal("%s: Unsupported distance unit in item '%s'!\n", module, str);
+ fatal("%s: Unsupported distance unit in item '%s'!\n", module, qPrintable(str));
}
return 2;
}
-int
-parse_distance(const QString& str, double* val, double scale, const char* module)
-{
- return parse_distance(CSTR(str), val, scale, module);
-}
-
/*
* parse_speed:
*
* module: calling module, i.e. "garmin_txt"
*/
int
-parse_speed(const char* str, double* val, const double scale, const char* module)
+parse_speed(const QString& str, double* val, const double scale, const char* module)
{
- char* unit;
- if ((str == nullptr) || (*str == '\0')) {
+ if (str.isEmpty()) {
return 0;
}
- *val = strtod(str, &unit);
- if (unit == nullptr) {
- fatal("%s: Unconvertible numeric value (%s)!\n", module, str);
- }
+ QString unit;
+ constexpr bool* dieonfailure = nullptr;
+ *val = parse_double(str, module, dieonfailure, &unit);
- while (isspace(*unit)) {
- unit++;
- }
+ unit = unit.trimmed();
- if (*unit == '\0') {
+ if (unit.isEmpty()) {
*val *= scale;
return 1;
}
} else if (case_ignore_strcmp(unit, "mih") == 0) {
*val = MPH_TO_MPS(*val);
} else {
- warning("%s: Unsupported speed unit '%s' in item '%s'!\n", module, unit, str);
+ warning("%s: Unsupported speed unit '%s' in item '%s'!\n", module, qPrintable(unit), qPrintable(str));
}
return 2;
}
-int
-parse_speed(const QString& str, double* val, const double scale, const char* module)
-{
- return parse_speed(CSTR(str), val, scale, module);
-}
-
/*
* Convert string 'str' into geodetic latitude & longitude values. The format
* will be interpreted depending on 'grid' parameter.
QString line;
gpsbabel::TextStream stream;
- stream.open(polyfileopt.get(), QIODevice::ReadOnly, MYNAME);
+ stream.open(polyfileopt, QIODevice::ReadOnly, MYNAME);
double olat = BADVAL;
double olon = BADVAL;
#include "defs.h" // for ARG_NOMINMAX, arglist_t, ARGTYPE_BOOL, ARGTYPE_FILE
#include "filter.h" // for Filter
-#include "option.h" // for OptionBool, OptionCString
+#include "option.h" // for OptionBool, OptionString
#if FILTERS_ENABLED
/* Data Members */
- OptionCString polyfileopt;
+ OptionString polyfileopt;
OptionBool exclopt;
QVector<arglist_t> args = {
#include "position.h"
#include <cmath> // for abs
-#include <cstdlib> // for strtod, abs
+#include <cstdlib> // for abs
#include <QList> // for QList
#include <QtGlobal> // for qRound64, qint64
max_diff_time = 0;
check_time = false;
- if (distopt != nullptr) {
+ if (distopt) {
if (parse_distance(distopt, &pos_dist, kMetersPerFoot, MYNAME) == 0) {
fatal(MYNAME ": No distance specified with distance option.\n");
}
}
- if (timeopt != nullptr) {
+ if (timeopt) {
check_time = true;
- max_diff_time = qRound64(strtod(timeopt, nullptr) * 1000.0);
+ max_diff_time = qRound64(timeopt.get_result() * 1000.0);
}
}
#include "defs.h" // for arglist_t, route_head (ptr only), ARG_NOMINMAX, ARGTYPE_FLOAT, ARGTYPE_REQUIRED, ARGTYPE_BOOL, Waypoint, WaypointList (ptr only)
#include "filter.h" // for Filter
-#include "option.h" // for OptionCString, OptionBool
+#include "option.h" // for OptionString, OptionBool
#if FILTERS_ENABLED
double pos_dist{};
qint64 max_diff_time{};
- OptionCString distopt;
- OptionCString timeopt;
+ OptionDouble distopt;
+ OptionDouble timeopt;
OptionBool purge_duplicates;
bool check_time{};
QVector<arglist_t> args = {
{
"distance", &distopt, "Maximum positional distance",
- nullptr, ARGTYPE_FLOAT | ARGTYPE_REQUIRED, ARG_NOMINMAX, nullptr
+ nullptr, ARGTYPE_ALLOW_TRAILING_DATA | ARGTYPE_STRING | ARGTYPE_REQUIRED, ARG_NOMINMAX, nullptr
},
{
"all", &purge_duplicates,
#include "radius.h"
-#include <cstdlib> // for strtod
#include <utility> // for as_const
#include <QString> // for QString
#include <QtGlobal> // QAddConst<>::Type, foreach
-#include "defs.h" // for Waypoint, del_marked_wpts, route_add_head, route_add_wpt, waypt_add, waypt_sort, waypt_swap, xstrtoi, route_head, WaypointList, kMilesPerKilometer
+#include "defs.h" // for Waypoint, del_marked_wpts, route_add_head, route_add_wpt, waypt_add, waypt_sort, waypt_swap, route_head, WaypointList, kMilesPerKilometer
#include "grtcirc.h" // for gcdist, radtomiles
}
route_head* rte_head = nullptr;
- if (routename != nullptr) {
+ if (routename) {
rte_head = new route_head;
rte_head->rte_name = routename;
route_add_head(rte_head);
delete static_cast<extra_data*>(wp->extra_data);
wp->extra_data = nullptr;
- if ((maxctarg != nullptr) && (i >= maxct)) {
+ if (maxctarg && (i >= maxct)) {
delete wp;
} else {
- if (routename != nullptr) {
+ if (routename) {
route_add_wpt(rte_head, wp);
} else {
waypt_add(wp);
{
pos_dist = 0;
- if (distopt != nullptr) {
+ if (distopt) {
if (parse_distance(distopt, &pos_dist, kMetersPerMile, MYNAME) == 0) {
fatal(MYNAME ": No distance specified with distance option.\n");
}
}
- if (maxctarg != nullptr) {
- maxct = xstrtoi(maxctarg, nullptr, 10);
+ if (maxctarg) {
+ maxct = maxctarg.get_result();
} else {
maxct = 0;
}
home_pos = new Waypoint;
- if (latopt != nullptr) {
- home_pos->latitude = strtod(latopt, nullptr);
+ if (latopt) {
+ home_pos->latitude = latopt.get_result();
}
- if (lonopt != nullptr) {
- home_pos->longitude = strtod(lonopt, nullptr);
+ if (lonopt) {
+ home_pos->longitude = lonopt.get_result();
}
}
#include "defs.h" // for arglist_t, ARG_NOMINMAX, ARGTYPE_FLOAT, ARGTYPE_REQUIRED, ARGTYPE_BOOL, ARGTYPE_INT, ARGTYPE_STRING, Waypoint
#include "filter.h" // for Filter
-#include "option.h" // for OptionCString, OptionBool
+#include "option.h" // for OptionString, OptionBool
#if FILTERS_ENABLED
/* Data Members */
double pos_dist{};
- OptionCString distopt;
- OptionCString latopt;
- OptionCString lonopt;
+ OptionDouble distopt;
+ OptionDouble latopt;
+ OptionDouble lonopt;
OptionBool exclopt;
OptionBool nosort;
- OptionCString maxctarg;
- OptionCString routename;
+ OptionInt maxctarg;
+ OptionString routename;
int maxct{};
Waypoint* home_pos{};
},
{
"distance", &distopt, "Maximum distance from center",
- nullptr, ARGTYPE_FLOAT | ARGTYPE_REQUIRED, ARG_NOMINMAX, nullptr
+ nullptr, ARGTYPE_ALLOW_TRAILING_DATA | ARGTYPE_STRING | ARGTYPE_REQUIRED, ARG_NOMINMAX, nullptr
},
{
"exclude", &exclopt, "Exclude points close to center",
{
generator = new std::mt19937;
if (opt_seed) {
- generator->seed(xstrtoi(opt_seed, nullptr, 10));
+ generator->seed(opt_seed.get_result());
} else {
generator->seed(gpsbabel_time);
}
Waypoint* prev = nullptr;
QDateTime time = current_time().toUTC();
- int points = (opt_points) ? xstrtoi(opt_points, nullptr, 10) : rand_int(128) + 1;
+ int points = opt_points? opt_points.get_result() : rand_int(128) + 1;
if (doing_trks || doing_rtes) {
head = new route_head;
if (doing_trks) {
random_set_generator();
realtime = new realtime_data;
if (opt_points) {
- realtime->points = xstrtoi(opt_points, nullptr, 10);
+ realtime->points = opt_points.get_result();
}
realtime->time = current_time().toUTC();
}
#include "defs.h"
#include "format.h" // for Format
-#include "option.h" // for OptionCString, OptionBool
+#include "option.h" // for OptionString, OptionBool
class RandomFormat : public Format
/* Data Members */
- OptionCString opt_points;
- OptionCString opt_seed;
+ OptionInt opt_points;
+ OptionInt opt_seed;
OptionBool opt_nodelay;
QVector<arglist_t> random_args = {
option arc file File containing vertices of arc file https://www.gpsbabel.org/WEB_DOC_DIR/filter_arc.html#fmt_arc_o_file
option arc rte Route(s) are vertices of arc boolean https://www.gpsbabel.org/WEB_DOC_DIR/filter_arc.html#fmt_arc_o_rte
option arc trk Track(s) are vertices of arc boolean https://www.gpsbabel.org/WEB_DOC_DIR/filter_arc.html#fmt_arc_o_trk
-option arc distance Maximum distance from arc float https://www.gpsbabel.org/WEB_DOC_DIR/filter_arc.html#fmt_arc_o_distance
+option arc distance Maximum distance from arc string https://www.gpsbabel.org/WEB_DOC_DIR/filter_arc.html#fmt_arc_o_distance
option arc exclude Exclude points close to the arc boolean https://www.gpsbabel.org/WEB_DOC_DIR/filter_arc.html#fmt_arc_o_exclude
option arc points Use distance from vertices not lines boolean https://www.gpsbabel.org/WEB_DOC_DIR/filter_arc.html#fmt_arc_o_points
option arc project Move waypoints to its projection on lines or vertices boolean https://www.gpsbabel.org/WEB_DOC_DIR/filter_arc.html#fmt_arc_o_project
radius Include Only Points Within Radius https://www.gpsbabel.org/WEB_DOC_DIR/filter_radius.html
option radius lat Latitude for center point (D.DDDDD) float https://www.gpsbabel.org/WEB_DOC_DIR/filter_radius.html#fmt_radius_o_lat
option radius lon Longitude for center point (D.DDDDD) float https://www.gpsbabel.org/WEB_DOC_DIR/filter_radius.html#fmt_radius_o_lon
-option radius distance Maximum distance from center float https://www.gpsbabel.org/WEB_DOC_DIR/filter_radius.html#fmt_radius_o_distance
+option radius distance Maximum distance from center string https://www.gpsbabel.org/WEB_DOC_DIR/filter_radius.html#fmt_radius_o_distance
option radius exclude Exclude points close to center boolean https://www.gpsbabel.org/WEB_DOC_DIR/filter_radius.html#fmt_radius_o_exclude
option radius nosort Inhibit sort by distance to center boolean https://www.gpsbabel.org/WEB_DOC_DIR/filter_radius.html#fmt_radius_o_nosort
option radius maxcount Output no more than this number of points integer 1 https://www.gpsbabel.org/WEB_DOC_DIR/filter_radius.html#fmt_radius_o_maxcount
option interpolate distance Distance interval string https://www.gpsbabel.org/WEB_DOC_DIR/filter_interpolate.html#fmt_interpolate_o_distance
option interpolate route Interpolate routes instead boolean https://www.gpsbabel.org/WEB_DOC_DIR/filter_interpolate.html#fmt_interpolate_o_route
height Manipulate altitudes https://www.gpsbabel.org/WEB_DOC_DIR/filter_height.html
-option height add Adds a constant value to every altitude float https://www.gpsbabel.org/WEB_DOC_DIR/filter_height.html#fmt_height_o_add
+option height add Adds a constant value to every altitude string https://www.gpsbabel.org/WEB_DOC_DIR/filter_height.html#fmt_height_o_add
option height wgs84tomsl Converts WGS84 ellipsoidal height to orthometric height (MSL) boolean https://www.gpsbabel.org/WEB_DOC_DIR/filter_height.html#fmt_height_o_wgs84tomsl
track Manipulate track lists https://www.gpsbabel.org/WEB_DOC_DIR/filter_track.html
option track move Correct trackpoint timestamps by a delta string https://www.gpsbabel.org/WEB_DOC_DIR/filter_track.html#fmt_track_o_move
option duplicate all Suppress all instances of duplicates boolean https://www.gpsbabel.org/WEB_DOC_DIR/filter_duplicate.html#fmt_duplicate_o_all
option duplicate correct Use coords from duplicate points boolean https://www.gpsbabel.org/WEB_DOC_DIR/filter_duplicate.html#fmt_duplicate_o_correct
position Remove Points Within Distance https://www.gpsbabel.org/WEB_DOC_DIR/filter_position.html
-option position distance Maximum positional distance float https://www.gpsbabel.org/WEB_DOC_DIR/filter_position.html#fmt_position_o_distance
+option position distance Maximum positional distance string https://www.gpsbabel.org/WEB_DOC_DIR/filter_position.html#fmt_position_o_distance
option position all Suppress all points close to other points boolean https://www.gpsbabel.org/WEB_DOC_DIR/filter_position.html#fmt_position_o_all
option position time Maximum time in seconds between two points float https://www.gpsbabel.org/WEB_DOC_DIR/filter_position.html#fmt_position_o_time
discard Remove unreliable points with high hdop or vdop https://www.gpsbabel.org/WEB_DOC_DIR/filter_discard.html
option discard hdop Suppress points with higher hdop float -1.0 https://www.gpsbabel.org/WEB_DOC_DIR/filter_discard.html#fmt_discard_o_hdop
option discard vdop Suppress points with higher vdop float -1.0 https://www.gpsbabel.org/WEB_DOC_DIR/filter_discard.html#fmt_discard_o_vdop
option discard hdopandvdop Link hdop and vdop suppression with AND boolean https://www.gpsbabel.org/WEB_DOC_DIR/filter_discard.html#fmt_discard_o_hdopandvdop
-option discard sat Minimum sats to keep points integer -1.0 https://www.gpsbabel.org/WEB_DOC_DIR/filter_discard.html#fmt_discard_o_sat
+option discard sat Minimum sats to keep points integer -1 https://www.gpsbabel.org/WEB_DOC_DIR/filter_discard.html#fmt_discard_o_sat
option discard fixnone Suppress points without fix boolean https://www.gpsbabel.org/WEB_DOC_DIR/filter_discard.html#fmt_discard_o_fixnone
option discard fixunknown Suppress points with unknown fix boolean https://www.gpsbabel.org/WEB_DOC_DIR/filter_discard.html#fmt_discard_o_fixunknown
option discard elemin Suppress points below given elevation in meters integer https://www.gpsbabel.org/WEB_DOC_DIR/filter_discard.html#fmt_discard_o_elemin
file rwrwrw garmin_txt txt Garmin MapSource - txt (tab delimited) garmin_txt
https://www.gpsbabel.org/WEB_DOC_DIR/fmt_garmin_txt.html
-option garmin_txt date Read/Write date format (i.e. yyyy/mm/dd) string https://www.gpsbabel.org/WEB_DOC_DIR/fmt_garmin_txt.html#fmt_garmin_txt_o_date
+option garmin_txt date Read/Write date format (i.e. yyyy/mm/dd) string dd/mm/yyyy https://www.gpsbabel.org/WEB_DOC_DIR/fmt_garmin_txt.html#fmt_garmin_txt_o_date
option garmin_txt datum GPS datum (def. WGS 84) string WGS 84 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_garmin_txt.html#fmt_garmin_txt_o_datum
option garmin_txt temp Temperature unit [c=Celsius, f=Fahrenheit] string c https://www.gpsbabel.org/WEB_DOC_DIR/fmt_garmin_txt.html#fmt_garmin_txt_o_temp
-option garmin_txt time Read/Write time format (i.e. HH:mm:ss xx) string https://www.gpsbabel.org/WEB_DOC_DIR/fmt_garmin_txt.html#fmt_garmin_txt_o_time
+option garmin_txt time Read/Write time format (i.e. HH:mm:ss xx) string HH:mm:ss https://www.gpsbabel.org/WEB_DOC_DIR/fmt_garmin_txt.html#fmt_garmin_txt_o_time
option garmin_txt utc Write timestamps with offset x to UTC time integer -23 +23 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_garmin_txt.html#fmt_garmin_txt_o_utc
{
if (averageopt) {
- bool ok;
- average_count = QString(averageopt).toInt(&ok);
- if (!ok || average_count < 2) {
+ average_count = averageopt.get_result();
+ if (average_count < 2) {
fatal(FatalMsg() << MYNAME ": the average count must be greater than one.");
}
}
if (decimateopt) {
- bool ok;
- decimate_count = QString(decimateopt).toInt(&ok);
- if (!ok || decimate_count < 2) {
+ decimate_count = decimateopt.get_result();
+ if (decimate_count < 2) {
fatal(FatalMsg() << MYNAME ": the decimate count must be greater than one.");
}
}
if (interpolateopt) {
- bool ok;
- interpolate_count = QString(interpolateopt).toInt(&ok);
- if (!ok || interpolate_count < 2) {
+ interpolate_count = interpolateopt.get_result();
+ if (interpolate_count < 2) {
fatal(FatalMsg() << MYNAME ": the interpolate count must be greater than one.");
}
if (!averageopt || average_count < interpolate_count) {
#include "defs.h" // for arglist_t, ARGTYPE_INT, Waypoint, route_head
#include "filter.h" // for Filter
-#include "option.h" // for OptionCString
+#include "option.h" // for OptionString
#include "src/core/nvector.h" // for NVector
int decimate_count{0};
int interpolate_count{0};
- OptionCString decimateopt;
- OptionCString interpolateopt;
- OptionCString averageopt;
+ OptionInt decimateopt;
+ OptionInt interpolateopt;
+ OptionInt averageopt;
QVector<arglist_t> args = {
{
#include "defs.h" // for arglist_t, ARGTYPE_STRING, Waypoint, route_head, FF_CAP_RW_ALL, ff_cap, ff_type, ff_type_file
#include "format.h" // for Format
-#include "option.h" // for OptionCString
+#include "option.h" // for OptionString
#if SHAPELIB_ENABLED
#if HAVE_LIBSHAPE
# include <shapefil.h>
QString ofname;
int nameFieldIdx{}; // the field index of the field with fieldName "name" in the output DBF.
- OptionCString opt_name;
- OptionCString opt_url;
+ OptionString opt_name;
+ OptionString opt_url;
QVector<arglist_t> shp_args = {
{
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#include <algorithm> // for max, min
#include <cctype> // for isprint
#include <cmath> // for cos, sin, atan2, pow, sqrt
#include <cstdarg> // for va_end, va_list, va_start
#define res_PROTOCOL_ERR -3
#define res_NOTFOUND -4
-#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
-#define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
-
void
SkytraqBase::db(int l, const char* msg, ...)
0x00 // reserved
};
- if (opt_configure_logging) {
- if (*opt_configure_logging) {
- unsigned int nn = sscanf(opt_configure_logging, "%u:%u:%u:%u", &tmin, &tmax, &dmin, &dmax);
- if (nn>3) {
- db(0, "Reconfiguring logging to: tmin=%u, tmax=%u, dmin=%u, dmax=%u\n", tmin, tmax, dmin, dmax);
- be_write32(MSG_LOG_CONFIGURE_CONTROL+5, tmin);
- be_write32(MSG_LOG_CONFIGURE_CONTROL+1, tmax);
- be_write32(MSG_LOG_CONFIGURE_CONTROL+13, dmin);
- be_write32(MSG_LOG_CONFIGURE_CONTROL+9, dmax);
- } else {
- db(1, MYNAME "Option usage: configlog=tmin:tmax:dmin:dmax");
- return -1;
- }
+ if (!opt_configure_logging.isEmpty()) {
+ unsigned int nn = sscanf(opt_configure_logging.get().toUtf8(), "%u:%u:%u:%u", &tmin, &tmax, &dmin, &dmax);
+ if (nn>3) {
+ db(0, "Reconfiguring logging to: tmin=%u, tmax=%u, dmin=%u, dmax=%u\n", tmin, tmax, dmin, dmax);
+ be_write32(MSG_LOG_CONFIGURE_CONTROL+5, tmin);
+ be_write32(MSG_LOG_CONFIGURE_CONTROL+1, tmax);
+ be_write32(MSG_LOG_CONFIGURE_CONTROL+13, dmin);
+ be_write32(MSG_LOG_CONFIGURE_CONTROL+9, dmax);
+ } else {
+ db(1, MYNAME "Option usage: configlog=tmin:tmax:dmin:dmax");
+ return -1;
}
}
*/
qint64 gps_timet = 315964800; /* Jan 06 1980 0:00 UTC */
- int week_rollover = xstrtoi(opt_gps_week_rollover, nullptr, 10);
+ int week_rollover = opt_gps_week_rollover.get_result();
if (week_rollover < 0) {
int current_week = (QDateTime::currentSecsSinceEpoch() - gps_timet)/
(7*SECONDS_PER_DAY);
}
gps_timet += (week+week_rollover*1024)*7*SECONDS_PER_DAY + sec;
- int override = xstrtoi(opt_gps_utc_offset, nullptr, 10);
+ int override = opt_gps_utc_offset.get_result();
if (override) {
gps_timet -= override;
return QDateTime::fromSecsSinceEpoch(gps_timet, QtUTC);
rd_char(&errors);
rd_char(&errors);
rd_char(&errors);
- skytraq_set_baud(xstrtoi(opt_dlbaud, nullptr, 10));
+ skytraq_set_baud(opt_dlbaud.get_result());
#endif
cs = skytraq_calc_checksum(buf, i);
int rc;
int got_sectors;
int total_sectors_read = 0;
- int read_at_once = MAX(xstrtoi(opt_read_at_once, nullptr, 10), 1);
- int opt_first_sector_val = xstrtoi(opt_first_sector, nullptr, 10);
- int opt_last_sector_val = xstrtoi(opt_last_sector, nullptr, 10);
+ int read_at_once = std::max(opt_read_at_once.get_result(), 1);
+ int opt_first_sector_val = opt_first_sector.get_result();
+ int opt_last_sector_val = opt_last_sector.get_result();
int multi_read_supported = 1;
gbfile* dumpfile = nullptr;
sectors_used_b = (log_wr_ptr + SECTOR_SIZE - 1) / SECTOR_SIZE;
if (sectors_used_a != sectors_used_b) {
db(1, "Warning: device reported inconsistent number of used sectors (a=%i, b=%i), "\
- "using max=%i\n", sectors_used_a, sectors_used_b, MAX(sectors_used_a, sectors_used_b));
+ "using max=%i\n", sectors_used_a, sectors_used_b, std::max(sectors_used_a, sectors_used_b));
}
- sectors_used = MAX(sectors_used_a, sectors_used_b);
+ sectors_used = std::max(sectors_used_a, sectors_used_b);
*/
if (opt_last_sector_val < 0) {
sectors_used = sectors_total - sectors_free + 1 /*+5*/;
// m.ad/090930: removed code that tried reducing read_at_once if necessary since doesn't work with xmalloc
if (opt_dump_file) {
- dumpfile = gbfopen(opt_dump_file.get(), "w", MYNAME);
+ dumpfile = gbfopen(opt_dump_file, "w", MYNAME);
}
db(1, MYNAME ": Reading log data from device...\n");
db(1, MYNAME ": opt_last_sector_val=%d\n", opt_last_sector_val);
for (int i = opt_first_sector_val; i < sectors_used; i += got_sectors) {
for (t = 0, got_sectors = 0; (t < SECTOR_RETRIES) && (got_sectors <= 0); t++) {
- if (xstrtoi(opt_read_at_once, nullptr, 10) == 0 || multi_read_supported == 0) {
+ if (opt_read_at_once.get_result() == 0 || multi_read_supported == 0) {
rc = skytraq_read_single_sector(i, buffer);
if (rc == res_OK) {
got_sectors = 1;
}
} else {
/* Try to read read_at_once sectors at once.
- * If tere aren't any so many interesting ones, read the remainder (sectors_used-i).
+ * If there aren't so many interesting ones, read the remainder (sectors_used-i).
* And read at least 1 sector.
*/
- read_at_once = MAX(MIN(read_at_once, sectors_used-i), 1);
+ read_at_once = std::max(std::min(read_at_once, sectors_used-i), 1);
rc = skytraq_read_multiple_sectors(i, read_at_once, buffer);
switch (rc) {
case res_OK:
got_sectors = read_at_once;
- read_at_once = MIN(read_at_once*2, xstrtoi(opt_read_at_once, nullptr, 10));
+ read_at_once = std::min(read_at_once*2, opt_read_at_once.get_result());
break;
case res_NACK:
default:
/* On failure, try with less sectors */
- read_at_once = MAX(read_at_once/2, 1);
+ read_at_once = std::max(read_at_once/2, 1);
}
}
}
{
int baud_rates[] = { 9600, 230400, 115200, 57600, 4800, 19200, 38400 };
int baud_rates_count = sizeof(baud_rates)/sizeof(baud_rates[0]);
- int initbaud = xstrtoi(opt_initbaud, nullptr, 10);
+ int initbaud = opt_initbaud.get_result();
uint8_t MSG_QUERY_SOFTWARE_VERSION[2] = { 0x02, 0x01 };
struct {
uint8_t id;
uint8_t MSG_SET_LOCATION[17] = { 0x36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
uint8_t MSG_GET_LOCATION = 0x35;
- db(3, MYNAME ": set_location='%s'\n", qPrintable(opt_set_location.get()));
+ db(3, MYNAME ": set_location='%s'\n", qPrintable(opt_set_location));
- sscanf(opt_set_location, "%lf:%lf", &lat, &lng);
+ sscanf(opt_set_location.get().toUtf8(), "%lf:%lf", &lat, &lng);
le_write_double(&MSG_SET_LOCATION[1], lat);
le_write_double(&MSG_SET_LOCATION[9], lng);
for (unsigned char i : MSG_SET_LOCATION) {
return;
}
- int dlbaud = xstrtoi(opt_dlbaud, nullptr, 10);
+ int dlbaud = opt_dlbaud.get_result();
if (dlbaud != 0 && dlbaud != skytraq_baud) {
skytraq_set_baud(dlbaud);
}
// read device unless no-output=true and dump-file=0 (i.e. no data needed at all)
- if (!opt_no_output || opt_dump_file != nullptr) {
+ if (!opt_no_output || opt_dump_file) {
skytraq_read_tracks();
}
{
read_state st;
int got_bytes;
- int opt_first_sector_val = xstrtoi(opt_first_sector, nullptr, 10);
- int opt_last_sector_val = xstrtoi(opt_last_sector, nullptr, 10);
+ int opt_first_sector_val = opt_first_sector.get_result();
+ int opt_last_sector_val = opt_last_sector.get_result();
state_init(&st);
auto* buffer = (uint8_t*) xmalloc(SECTOR_SIZE);
* -1 in case of errors
* the number of the POI will not be checked - if it is not correct, miniHome will send NACK
*/
-int MinihomerFormat::miniHomer_set_poi(uint16_t poinum, const char* opt_poi) const
+int MinihomerFormat::miniHomer_set_poi(uint16_t poinum, const QString& opt_poi) const
{
#define MSG_SET_POI_SIZE (sizeof(uint8_t)+sizeof(uint16_t)+3*sizeof(double)+sizeof(uint8_t))
uint8_t MSG_SET_POI[MSG_SET_POI_SIZE] = {
int result = 0; // result will be 0 if opt_poi isn't set
- if (opt_poi) { // first check opt_poi
- if (*opt_poi) {
- lat=lng=alt=0.0;
- /*
- * parse format of <lat>:<lng>[:alt]
- * we assume at least two elements in the value string
- */
- int n = sscanf(opt_poi, "%lf:%lf:%lf", &lat, &lng, &alt);
- if (n >= 2) {
- db(3, "found %d elems '%s':poi=%s@%d, lat=%f, lng=%f, alt=%f\n", n, opt_poi, poinames[poinum], poinum, lat, lng, alt);
- lla2ecef(lat, lng, alt, &ecef_x, &ecef_y, &ecef_z);
- db(1, MYNAME ": set POI[%s]='%f %f %f/%f %f %f'\n", poinames[poinum], lat, lng, alt, ecef_x, ecef_y, ecef_z);
- be_write16(MSG_SET_POI+1, poinum);
- be_write_double(MSG_SET_POI+3, ecef_x);
- be_write_double(MSG_SET_POI+11, ecef_y);
- be_write_double(MSG_SET_POI+19, ecef_z);
- MSG_SET_POI[27]=0;
- if (skytraq_wr_msg_verify((uint8_t*)&MSG_SET_POI, sizeof(MSG_SET_POI)) == res_OK) {
- result=1;
- } else {
- warning(MYNAME ": cannot set poi %d '%s'\n", poinum, poinames[poinum]);
- result=-1;
- }
+ if (!opt_poi.isEmpty()) { // first check opt_poi
+ lat=lng=alt=0.0;
+ /*
+ * parse format of <lat>:<lng>[:alt]
+ * we assume at least two elements in the value string
+ */
+ int n = sscanf(opt_poi.toUtf8(), "%lf:%lf:%lf", &lat, &lng, &alt);
+ if (n >= 2) {
+ db(3, "found %d elems '%s':poi=%s@%d, lat=%f, lng=%f, alt=%f\n", n, qPrintable(opt_poi), poinames[poinum], poinum, lat, lng, alt);
+ lla2ecef(lat, lng, alt, &ecef_x, &ecef_y, &ecef_z);
+ db(1, MYNAME ": set POI[%s]='%f %f %f/%f %f %f'\n", poinames[poinum], lat, lng, alt, ecef_x, ecef_y, ecef_z);
+ be_write16(MSG_SET_POI+1, poinum);
+ be_write_double(MSG_SET_POI+3, ecef_x);
+ be_write_double(MSG_SET_POI+11, ecef_y);
+ be_write_double(MSG_SET_POI+19, ecef_z);
+ MSG_SET_POI[27]=0;
+ if (skytraq_wr_msg_verify((uint8_t*)&MSG_SET_POI, sizeof(MSG_SET_POI)) == res_OK) {
+ result=1;
} else {
- warning(MYNAME ": argument to %s needs to be like <lat>:<lng>[:<alt>]\n", poinames[poinum]);
+ warning(MYNAME ": cannot set poi %d '%s'\n", poinum, poinames[poinum]);
result=-1;
}
+ } else {
+ warning(MYNAME ": argument to %s needs to be like <lat>:<lng>[:<alt>]\n", poinames[poinum]);
+ result=-1;
}
}
return result;
skytraq_rd_deinit();
mhport.clear();
}
-#define SETPOI(poinum, poiname) if (opt_set_poi_##poiname ) {miniHomer_set_poi(poinum, opt_set_poi_##poiname);}
void
MinihomerFormat::read()
{
#include "defs.h"
#include "format.h" // for Format
#include "gbfile.h" // for gbfile
-#include "option.h" // for OptionCString, OptionBool
+#include "option.h" // for OptionString, OptionBool
class SkytraqBase
int skytraq_baud = 0; /* detected baud rate */
OptionBool opt_erase; /* erase after read? (0/1) */
- OptionCString opt_initbaud; /* baud rate used to init device */
- OptionCString opt_dlbaud; /* baud rate used for downloading tracks */
- OptionCString opt_read_at_once; /* number of sectors to read at once (Venus6 only) */
- OptionCString opt_first_sector; /* first sector to be read from the device (default: 0) */
- OptionCString opt_last_sector; /* last sector to be read from the device (default: smart read everything) */
- OptionCString opt_dump_file; /* dump raw data to this file (optional) */
+ OptionInt opt_initbaud; /* baud rate used to init device */
+ OptionInt opt_dlbaud; /* baud rate used for downloading tracks */
+ OptionInt opt_read_at_once; /* number of sectors to read at once (Venus6 only) */
+ OptionInt opt_first_sector; /* first sector to be read from the device (default: 0) */
+ OptionInt opt_last_sector; /* last sector to be read from the device (default: smart read everything) */
+ OptionString opt_dump_file; /* dump raw data to this file (optional) */
OptionBool opt_no_output; /* disable output? (0/1) */
- OptionCString opt_set_location; /* set if the "targetlocation" options was used */
- OptionCString opt_configure_logging;
- OptionCString opt_gps_utc_offset;
- OptionCString opt_gps_week_rollover;
+ OptionString opt_set_location; /* set if the "targetlocation" options was used */
+ OptionString opt_configure_logging;
+ OptionInt opt_gps_utc_offset;
+ OptionInt opt_gps_week_rollover;
};
class SkytraqFormat : public Format, private SkytraqBase
static void lla2ecef(double lat, double lng, double alt, double* ecef_x, double* ecef_y, double* ecef_z);
void miniHomer_get_poi() const;
- int miniHomer_set_poi(uint16_t poinum, const char* opt_poi) const;
+ int miniHomer_set_poi(uint16_t poinum, const QString& opt_poi) const;
/* Data Members */
- OptionCString opt_set_poi_home; /* set if a "poi" option was used */
- OptionCString opt_set_poi_car; /* set if a "poi" option was used */
- OptionCString opt_set_poi_boat; /* set if a "poi" option was used */
- OptionCString opt_set_poi_heart; /* set if a "poi" option was used */
- OptionCString opt_set_poi_bar; /* set if a "poi" option was used */
+ OptionString opt_set_poi_home; /* set if a "poi" option was used */
+ OptionString opt_set_poi_car; /* set if a "poi" option was used */
+ OptionString opt_set_poi_boat; /* set if a "poi" option was used */
+ OptionString opt_set_poi_heart; /* set if a "poi" option was used */
+ OptionString opt_set_poi_bar; /* set if a "poi" option was used */
QVector<arglist_t> miniHomer_args = {
{ "baud", &opt_dlbaud, "Baud rate used for download", "115200", ARGTYPE_INT, "0", "115200", nullptr },
*/
#include <cassert>
-#include <cstdlib> // for strtod, strtol
#include <iterator> // for prev
#include <QDateTime> // for QDateTime
switch (limit_basis) {
case limit_basis_t::count:
- count = strtol(countopt, nullptr, 10);
+ count = countopt.get_result();
break;
case limit_basis_t::error: {
if (metric == metric_t::relative) {
- error = strtod(erroropt, nullptr);
+ error = erroropt.get_result();
} else {
if (parse_distance(erroropt, &error, kMetersPerMile, MYNAME) == 0) {
fatal(MYNAME ": No value specified with error option.\n");
#include "defs.h"
#include "filter.h" // for Filter
-#include "option.h" // for OptionBool, OptionCString
+#include "option.h" // for OptionBool, OptionString
#if FILTERS_ENABLED
limit_basis_t limit_basis{limit_basis_t::error};
metric_t metric{metric_t::crosstrack};
- OptionCString countopt;
- OptionCString erroropt;
+ OptionInt countopt;
+ OptionDouble erroropt;
OptionBool xteopt;
OptionBool lenopt;
OptionBool relopt;
},
{
"error", &erroropt, "Maximum error", nullptr,
- ARGTYPE_STRING | ARGTYPE_END_REQ | ARGTYPE_END_EXCL, "0", nullptr, nullptr
+ ARGTYPE_ALLOW_TRAILING_DATA | ARGTYPE_STRING | ARGTYPE_END_REQ | ARGTYPE_END_EXCL, "0", nullptr, nullptr
},
{
"crosstrack", &xteopt, "Use cross-track error (default)", nullptr,
}
if (opt_depth) {
- swapdepth = xstrtoi(opt_depth, nullptr, 10);
+ swapdepth = opt_depth.get_result();
}
if (opt_push) {
if (opt_pop || opt_append || opt_discard || opt_replace ||
#include "defs.h" // for ARGTYPE_BOOL, ARG_NOMINMAX, ARGTYPE_BEGIN_EXCL
#include "filter.h" // for Filter
-#include "option.h" // for OptionBool, OptionCString
+#include "option.h" // for OptionBool, OptionString
#if FILTERS_ENABLED
OptionBool opt_discard;
OptionBool opt_replace;
OptionBool opt_swap;
- OptionCString opt_depth;
+ OptionInt opt_depth;
OptionBool nowarn;
int warnings_enabled = 1;
int swapdepth = 0;
starttime.hour(), starttime.minute(), starttime.second(), starttime.msec(),
endtime.hour(), endtime.minute(), endtime.second(), endtime.msec());
- for (const char* c = static_cast<const char*>(opt_format); *c != '\0' ; c++) {
- char fmt;
+ const QByteArray format = opt_format.get().toUtf8();
+ for (auto it = format.cbegin(), end = format.cend(); it != end; ++it) {
- switch (*c) {
+ switch (*it) {
case '%':
- fmt = *++c;
- if (fmt == '\0') {
- fatal("No character after %% in subrip format");
+ if (++it == end) {
+ fatal("No character after %% in subrip format.\n");
}
- switch (fmt) {
+ switch (*it) {
case 's':
if (prevwpp->speed_has_value()) {
gbfprintf(fout, "%2.1f", MPS_TO_KPH(prevwpp->speed_value()));
break;
case '\\':
- fmt = *++c;
- if (fmt == '\0') {
- fatal("No character after \\ in subrip format");
+ if (++it == end) {
+ fatal("No character after \\ in subrip format.\n");
}
- switch (fmt) {
+
+ switch (*it) {
case 'n':
gbfprintf(fout, "\n");
break;
}
break;
+
default:
- gbfwrite(c, 1, 1, fout);
+ gbfputc(*it, fout);
}
}
gbfprintf(fout, "\n\n");
vspeed = 0;
gradient = 0;
- if ((opt_gpstime == nullptr) != (opt_gpsdate == nullptr)) {
+ if (opt_gpstime != opt_gpsdate) {
fatal(FatalMsg() << MYNAME ": Either both or neither of the gps_date and gps_time options must be supplied!");
}
gps_datetime = QDateTime();
- if ((opt_gpstime != nullptr) && (opt_gpsdate != nullptr)) {
- QDate gps_date = QDate::fromString(opt_gpsdate.get(), u"yyyyMMdd");
+ if (opt_gpstime && opt_gpsdate) {
+ QDate gps_date = QDate::fromString(opt_gpsdate, u"yyyyMMdd");
if (!gps_date.isValid()) {
- fatal(FatalMsg().nospace() << MYNAME ": option gps_date value (" << opt_gpsdate << ") is invalid. Expected yyyymmdd.");
+ fatal(FatalMsg().nospace() << MYNAME ": option gps_date value (" << opt_gpsdate.get() << ") is invalid. Expected yyyymmdd.");
}
- QTime gps_time = QTime::fromString(opt_gpstime.get(), u"HHmmss");
+ QTime gps_time = QTime::fromString(opt_gpstime, u"HHmmss");
if (!gps_time.isValid()) {
- gps_time = QTime::fromString(opt_gpstime.get(), u"HHmmss.z");
+ gps_time = QTime::fromString(opt_gpstime, u"HHmmss.z");
if (!gps_time.isValid()) {
- fatal(FatalMsg().nospace() << MYNAME ": option gps_time value (" << opt_gpstime << ") is invalid. Expected hhmmss[.sss]");
+ fatal(FatalMsg().nospace() << MYNAME ": option gps_time value (" << opt_gpstime.get() << ") is invalid. Expected hhmmss[.sss]");
}
}
gps_datetime = QDateTime(gps_date, gps_time, QtUTC);
}
video_offset_ms = 0;
- if (opt_videotime != nullptr) {
- QTime video_time = QTime::fromString(opt_videotime.get(), u"HHmmss");
+ if (opt_videotime) {
+ QTime video_time = QTime::fromString(opt_videotime, u"HHmmss");
if (!video_time.isValid()) {
- video_time = QTime::fromString(opt_videotime.get(), u"HHmmss.z");
+ video_time = QTime::fromString(opt_videotime, u"HHmmss.z");
if (!video_time.isValid()) {
- fatal(FatalMsg().nospace() << MYNAME ": option video_time value (" << opt_videotime << ") is invalid. Expected hhmmss[.sss].");
+ fatal(FatalMsg().nospace() << MYNAME ": option video_time value (" << opt_videotime.get() << ") is invalid. Expected hhmmss[.sss].");
}
}
video_offset_ms = video_time.msecsSinceStartOfDay();
#include "defs.h"
#include "format.h" // for Format
#include "gbfile.h" // for gbfprintf, gbfclose, gbfopen, gbfwrite, gbfile
-#include "option.h" // for OptionCString
+#include "option.h" // for OptionString
class SubripFormat : public Format
/* Data Members */
- OptionCString opt_videotime;
- OptionCString opt_gpstime;
- OptionCString opt_gpsdate;
- OptionCString opt_format;
+ OptionString opt_videotime;
+ OptionString opt_gpstime;
+ OptionString opt_gpsdate;
+ OptionString opt_format;
QDateTime gps_datetime; // Date time corresponding to video video_offset_ms
QDateTime video_datetime; // Date time corresponding to video time 00:00:00,000.
int video_offset_ms{0};
sed '/^LXXXGenerated by GPSBabel Version/d' ${TMPDIR}/igc.out > ${TMPDIR}/igc_sed3.out
compare ${REFERENCE}/igc1_3d.out ${TMPDIR}/igc_sed3.out
+gpsbabel -i gpx -f ${REFERENCE}/igc1_baro.gpx -i igc -f ${REFERENCE}/igc1_igc.out -o igc,timeadj=-129 -F ${TMPDIR}/igc.out
+sed '/^LXXXGenerated by GPSBabel Version/d' ${TMPDIR}/igc.out > ${TMPDIR}/igc_sed4.out
+compare ${REFERENCE}/igc1_3d.out ${TMPDIR}/igc_sed4.out
+
gpsbabel -i igc -f ${REFERENCE}/igc2.igc -o gpx -F ${TMPDIR}/igc2~igc.gpx
compare ${REFERENCE}/igc2_gpx.out ${TMPDIR}/igc2~igc.gpx
#include "text.h"
#include <QIODevice> // for QIODevice, QIODevice::WriteOnly
+#include <QRegularExpression> // for QRegularExpression
+#include <QRegularExpressionMatch> // for QRegularExpressionMatch
#include <QString> // for QString, operator!=
#include <QTextStream> // for QTextStream
#include <Qt> // for CaseInsensitive
file_out->open(fname, QIODevice::WriteOnly, MYNAME);
}
mkshort_handle = new MakeShort;
+
+ static const QRegularExpression re("^(?:ddd|dmm|dms)$");
+ assert(re.isValid());
+ if (re.match(opt_degformat).hasMatch()) {
+ degformat = opt_degformat.get().at(2).toLatin1();
+ } else {
+ fatal(MYNAME ": Unrecognized degformat %s, expected 'ddd', 'dmm' or 'dms'.\n", qPrintable(opt_degformat));
+ }
+
+ if (opt_altunits.get().startsWith('f')) {
+ altunits = 'f';
+ } else if (opt_altunits.get().startsWith('m')) {
+ altunits = 'm';
+ } else {
+ fatal(MYNAME ": Unrecognized altunits %s, expected 'f' for feet or 'm' for meters.\n", qPrintable(opt_altunits));
+ }
+
}
void
GPS_Math_WGS84_To_UTM_EN(wpt->latitude, wpt->longitude,
&utme, &utmn, &utmz, &utmzc);
QString position = QStringLiteral("%1 (%2%3 %4 %5)")
- .arg(pretty_deg_format(wpt->latitude, wpt->longitude, degformat[2], " ", false))
+ .arg(pretty_deg_format(wpt->latitude, wpt->longitude, degformat, " ", false))
.arg(utmz)
.arg(utmzc)
.arg(utme, 6, 'f', 0)
.arg(utmn, 7, 'f', 0);
if (wpt->altitude != unknown_alt) {
- position += QStringLiteral(" alt:%1").arg((int)((altunits[0]=='f') ? METERS_TO_FEET(wpt->altitude) : wpt->altitude));
+ position += QStringLiteral(" alt:%1").arg((int)((altunits == 'f') ? METERS_TO_FEET(wpt->altitude) : wpt->altitude));
}
QString sn = global_opts.synthesize_shortnames ? mkshort_handle->mkshort_from_wpt(wpt) : wpt->shortname;
*file_out << sn.leftJustified(16) << " " << position.rightJustified(59) << "\n";
if (logpart) {
double lat = logpart->xml_attribute("lat").toDouble();
double lon = logpart->xml_attribute("lon").toDouble();
- *file_out << pretty_deg_format(lat, lon, degformat[2], " ", false) << "\n";
+ *file_out << pretty_deg_format(lat, lon, degformat, " ", false) << "\n";
}
logpart = curlog->xml_findfirst(u"groundspeak:text");
#include "defs.h"
#include "format.h" // for Format
#include "mkshort.h" // for MakeShort
-#include "option.h" // for OptionBool, OptionCString
+#include "option.h" // for OptionBool, OptionString
#include "src/core/textstream.h" // for TextStream
OptionBool suppresssep;
OptionBool txt_encrypt;
OptionBool includelogs;
- OptionCString degformat;
- OptionCString altunits;
+ OptionString opt_degformat;
+ OptionString opt_altunits;
OptionBool split_output;
+ char degformat{};
+ char altunits{};
int waypoint_count{};
QString output_name;
"Include groundspeak logs if present", nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr
},
{
- "degformat", °format,
+ "degformat", &opt_degformat,
"Degrees output as 'ddd', 'dmm'(default) or 'dms'", "dmm", ARGTYPE_STRING, ARG_NOMINMAX, nullptr
},
{
- "altunits", &altunits,
+ "altunits", &opt_altunits,
"Units for altitude (f)eet or (m)etres", "m", ARGTYPE_STRING, ARG_NOMINMAX, nullptr
},
{
{
tpg_datum_idx = GPS_Lookup_Datum_Index(tpg_datum_opt);
if (tpg_datum_idx < 0) {
- fatal(MYNAME ": Datum '%s' is not recognized.\n", qPrintable(tpg_datum_opt.get()));
+ fatal(MYNAME ": Datum '%s' is not recognized.\n", qPrintable(tpg_datum_opt));
}
}
#include "format.h" // for Format
#include "gbfile.h" // for gbfile
#include "mkshort.h" // for MakeShort
-#include "option.h" // for OptionCString
+#include "option.h" // for OptionString
class TpgFormat : public Format
gbfile* tpg_file_in{};
gbfile* tpg_file_out{};
MakeShort* mkshort_handle{};
- OptionCString tpg_datum_opt;
+ OptionString tpg_datum_opt;
int tpg_datum_idx{};
int waypt_out_count{};
#include <cmath> // for nan
#include <cstdio> // for printf
#include <cstdlib> // for abs
-#include <cstring> // for strlen, strchr, strcmp
#include <ctime> // for gmtime, strftime, time_t, tm
#include <iterator> // for next
#include <utility> // for as_const
return res;
}
-qint64 TrackFilter::trackfilter_parse_time_opt(const char* arg)
+qint64 TrackFilter::trackfilter_parse_time_opt(const QString& arg)
{
qint64 result = 0;
qDebug() << MYNAME "-time option: shift =" << result / 1000.0 << "seconds";
}
} else {
- fatal(MYNAME "-time: invalid value in move option \"%s\"!\n", arg);
+ fatal(MYNAME "-time: invalid value in move option \"%s\"!\n", qPrintable(arg));
}
return result;
if (!opt_fix) {
return fix_unknown;
}
- if (!case_ignore_strcmp(opt_fix.get(), "pps")) {
+ if (!case_ignore_strcmp(opt_fix, "pps")) {
*nsats = 4;
return fix_pps;
}
- if (!case_ignore_strcmp(opt_fix.get(), "dgps")) {
+ if (!case_ignore_strcmp(opt_fix, "dgps")) {
*nsats = 4;
return fix_dgps;
}
- if (!case_ignore_strcmp(opt_fix.get(), "3d")) {
+ if (!case_ignore_strcmp(opt_fix, "3d")) {
*nsats = 4;
return fix_3d;
}
- if (!case_ignore_strcmp(opt_fix.get(), "2d")) {
+ if (!case_ignore_strcmp(opt_fix, "2d")) {
*nsats = 3;
return fix_2d;
}
- if (!case_ignore_strcmp(opt_fix.get(), "none")) {
+ if (!case_ignore_strcmp(opt_fix, "none")) {
*nsats = 0;
return fix_none;
}
return;
}
- if (opt_name != nullptr) {
- QRegularExpression regex(QRegularExpression::wildcardToRegularExpression(opt_name.get()),
+ if (opt_name) {
+ QRegularExpression regex(QRegularExpression::wildcardToRegularExpression(opt_name),
QRegularExpression::CaseInsensitiveOption);
if (!regex.isValid()) {
fatal(FatalMsg() << "track: name option is an invalid expression.");
}
if (need_time && (prev != nullptr) && (prev->GetCreationTime() > wpt->GetCreationTime())) {
- if (opt_merge == nullptr) {
+ if (!opt_merge) {
QString t1 = prev->CreationTimeXML();
QString t2 = wpt->CreationTimeXML();
fatal(MYNAME "-init: Track points badly ordered (timestamp %s > %s)!\n", qPrintable(t1), qPrintable(t2));
datetimestring = dt.toUTC().toString(u"yyyyMMdd");
}
- if ((opt_title != nullptr) && (strlen(opt_title) > 0)) {
- if (strchr(opt_title, '%') != nullptr) {
+ if (!opt_title.isEmpty()) {
+ if (opt_title.get().contains('%')) {
// Uggh. strftime format exposed to user.
time_t time = dt.toTime_t();
std::tm tm = *gmtime(&time);
char buff[128];
- strftime(buff, sizeof(buff), opt_title, &tm);
+ strftime(buff, sizeof(buff), opt_title.get().toUtf8(), &tm);
track->rte_name = buff;
} else {
track->rte_name = QStringLiteral("%1-%2").arg(opt_title.get(), datetimestring);
void TrackFilter::trackfilter_pack_init_rte_name(route_head* track, const gpsbabel::DateTime& default_time)
{
- if (strchr(opt_title, '%') != nullptr) {
+ if (opt_title.get().contains('%')) {
// Uggh. strftime format exposed to user.
gpsbabel::DateTime dt;
time_t t = dt.toTime_t();
std::tm tm = *gmtime(&t);
char buff[128];
- strftime(buff, sizeof(buff), opt_title, &tm);
+ strftime(buff, sizeof(buff), opt_title.get().toUtf8(), &tm);
track->rte_name = buff;
} else {
track->rte_name = opt_title;
void TrackFilter::trackfilter_title()
{
- if (opt_title == nullptr) {
+ if (!opt_title) {
return;
}
- if (strlen(opt_title) == 0) {
+ if (opt_title.isEmpty()) {
fatal(MYNAME "-title: Missing your title!\n");
}
for (auto* track : std::as_const(track_list)) {
/* check additional options */
- opt_interval = (opt_split && (strlen(opt_split) > 0) && (0 != strcmp(opt_split, TRACKFILTER_SPLIT_OPTION)));
+ opt_interval = (!opt_split.isEmpty() && (opt_split.get() != TRACKFILTER_SPLIT_OPTION));
if (opt_interval != 0) {
static const QRegularExpression re(R"(^([+-]?(?:\d+(?:\.\d*)?|\.\d+))([dhms])$)", QRegularExpression::CaseInsensitiveOption);
assert(re.isValid());
- QRegularExpressionMatch match = re.match(opt_split.get());
+ QRegularExpressionMatch match = re.match(opt_split);
if (match.hasMatch()) {
bool ok;
interval = match.captured(1).toDouble(&ok);
printf(MYNAME ": interval %f seconds\n", interval);
}
} else {
- fatal(MYNAME ": invalid timer interval specified \"%s\", must be a positive number, followed by 'd' for days, 'h' for hours, 'm' for minutes or 's' for seconds.\n", qPrintable(opt_split.get()));
+ fatal(MYNAME ": invalid timer interval specified \"%s\", must be a positive number, followed by 'd' for days, 'h' for hours, 'm' for minutes or 's' for seconds.\n", qPrintable(opt_split));
}
}
- opt_distance = (opt_sdistance && (strlen(opt_sdistance) > 0) && (0 != strcmp(opt_sdistance, TRACKFILTER_SDIST_OPTION)));
+ opt_distance = (!opt_sdistance.isEmpty() && (opt_sdistance.get() != TRACKFILTER_SDIST_OPTION));
if (opt_distance != 0) {
static const QRegularExpression re(R"(^([+-]?(?:\d+(?:\.\d*)?|\.\d+))([km])$)", QRegularExpression::CaseInsensitiveOption);
assert(re.isValid());
- QRegularExpressionMatch match = re.match(opt_sdistance.get());
+ QRegularExpressionMatch match = re.match(opt_sdistance);
if (match.hasMatch()) {
bool ok;
distance = match.captured(1).toDouble(&ok);
* option: "start" / "stop"
*******************************************************************************/
-QDateTime TrackFilter::trackfilter_range_check(const char* timestr)
+QDateTime TrackFilter::trackfilter_range_check(const QString& timestr)
{
QDateTime result;
- QString start(timestr);
QString fmtstart("00000101000000.000");
- fmtstart.replace(0, start.size(), start);
+ fmtstart.replace(0, timestr.size(), timestr);
static const QRegularExpression re(R"(^\d{14}\.\d{3}$)");
assert(re.isValid());
result.setTimeSpec(Qt::UTC);
#endif
if (!result.isValid()) {
- fatal(MYNAME "-range-check: Invalid timestamp \"%s\"!\n", timestr);
+ fatal(MYNAME "-range-check: Invalid timestamp \"%s\"!\n", qPrintable(timestr));
}
if constexpr(TRACKF_DBG) {
qDebug() << MYNAME "-range-check: " << result;
}
} else {
- fatal(MYNAME "-range-check: Invalid value for option \"%s\"!\n", timestr);
+ fatal(MYNAME "-range-check: Invalid value for option \"%s\"!\n", qPrintable(timestr));
}
return result;
QDateTime start; // constructed such that isValid() is false, unlike gpsbabel::DateTime!
QDateTime stop; // constructed such that isValid() is false, unlike gpsbabel::DateTime!
- if (opt_start != nullptr) {
+ if (opt_start) {
start = trackfilter_range_check(opt_start);
}
- if (opt_stop != nullptr) {
+ if (opt_stop) {
stop = trackfilter_range_check(opt_stop);
}
* option: "faketime"
*******************************************************************************/
-TrackFilter::faketime_t TrackFilter::trackfilter_faketime_check(const char* timestr)
+TrackFilter::faketime_t TrackFilter::trackfilter_faketime_check(const QString& timestr)
{
faketime_t result;
qDebug() << MYNAME "-faketime option: force =" << result.force << ", timestamp =" << result.start << ", step =" << result.step << "milliseconds";
}
} else {
- fatal(MYNAME "-faketime-check: Invalid value for faketime option \"%s\"!\n", timestr);
+ fatal(MYNAME "-faketime-check: Invalid value for faketime option \"%s\"!\n", qPrintable(timestr));
}
return result;
void TrackFilter::trackfilter_faketime()
{
- assert(opt_faketime != nullptr);
+ assert(opt_faketime);
faketime_t faketime = trackfilter_faketime_check(opt_faketime);
for (auto* track : std::as_const(track_list)) {
(trackfilter_opt_count() == 0) /* do pack by default */
);
/* in case of a formatted title we also need valid timestamps */
- if ((opt_title != nullptr) && (strchr(opt_title, '%') != nullptr)) {
+ if (opt_title && opt_title.get().contains('%')) {
need_time = true;
}
opts = -1; /* flag for do "pack" by default */
}
- if (opt_name != nullptr) {
+ if (opt_name) {
if (--opts == 0) {
return;
}
}
- if (opt_move != nullptr) { /* Correct timestamps before any other op */
+ if (opt_move) { /* Correct timestamps before any other op */
trackfilter_move();
if (--opts == 0) {
return;
}
}
- if ((opt_faketime != nullptr)) {
+ if (opt_faketime) {
opts--;
trackfilter_faketime();
}
}
- if ((opt_stop != nullptr) || (opt_start != nullptr)) {
- if (opt_start != nullptr) {
+ if (opt_stop || opt_start) {
+ if (opt_start) {
opts--;
}
- if (opt_stop != nullptr) {
+ if (opt_stop) {
opts--;
}
}
}
- if (opt_title != nullptr) {
+ if (opt_title) {
if (--opts == 0) {
trackfilter_title();
return;
if (opt_pack || (opts == -1)) { /* call our default option */
trackfilter_pack();
something_done = true;
- } else if (opt_merge != nullptr) {
+ } else if (opt_merge) {
trackfilter_merge();
something_done = true;
}
if (something_done && (--opts <= 0)) {
- if (opt_title != nullptr) {
+ if (opt_title) {
trackfilter_title();
}
return;
}
- if ((opt_split != nullptr) || (opt_sdistance != nullptr)) {
+ if (opt_split || opt_sdistance) {
trackfilter_split();
// track_list may? now be invalid!
}
// Performed last as previous options may have created "small" tracks.
- if (opt_minpoints != nullptr) {
- bool ok;
- minimum_points = QString(opt_minpoints).toInt(&ok);
- if (!ok || minimum_points <= 0) {
+ if (opt_minpoints) {
+ minimum_points = opt_minpoints.get_result();
+ if (minimum_points <= 0) {
fatal(MYNAME "-minimum_points: option value must be a positive integer!\n");
}
track_disp_all(trackfilter_minpoint_list_cb_f, nullptr, nullptr);
#include "defs.h" // for ARG_NOMINMAX, route_head (ptr only), ARG...
#include "filter.h" // for Filter
-#include "option.h" // for OptionCString, OptionBool
+#include "option.h" // for OptionString, OptionBool
#include "src/core/datetime.h" // for DateTime
#if FILTERS_ENABLED || MINIMAL_FILTERS
/* Member Functions */
int trackfilter_opt_count();
- static qint64 trackfilter_parse_time_opt(const char* arg);
+ static qint64 trackfilter_parse_time_opt(const QString& arg);
static bool trackfilter_init_sort_cb(const route_head* ha, const route_head* hb);
static bool trackfilter_merge_sort_cb(const Waypoint* wa, const Waypoint* wb);
fix_type trackfilter_parse_fix(int* nsats);
void trackfilter_split();
void trackfilter_move();
void trackfilter_synth();
- static QDateTime trackfilter_range_check(const char* timestr);
+ static QDateTime trackfilter_range_check(const QString& timestr);
void trackfilter_range();
void trackfilter_seg2trk();
void trackfilter_trk2seg();
- static faketime_t trackfilter_faketime_check(const char* timestr);
+ static faketime_t trackfilter_faketime_check(const QString& timestr);
void trackfilter_faketime();
static bool trackfilter_points_are_same(const Waypoint* wpta, const Waypoint* wptb);
static void trackfilter_segment_head(const route_head* rte);
/* Data Members */
- OptionCString opt_merge;
+ OptionString opt_merge;
OptionBool opt_pack;
- OptionCString opt_split;
- OptionCString opt_sdistance;
- OptionCString opt_move;
- OptionCString opt_title;
- OptionCString opt_start;
- OptionCString opt_stop;
- OptionCString opt_fix;
+ OptionString opt_split;
+ OptionString opt_sdistance;
+ OptionString opt_move;
+ OptionString opt_title;
+ OptionString opt_start;
+ OptionString opt_stop;
+ OptionString opt_fix;
OptionBool opt_course;
OptionBool opt_speed;
- OptionCString opt_name;
+ OptionString opt_name;
OptionBool opt_seg2trk;
OptionBool opt_trk2seg;
OptionBool opt_segment;
- OptionCString opt_faketime;
+ OptionString opt_faketime;
OptionBool opt_discard;
- OptionCString opt_minpoints;
+ OptionInt opt_minpoints;
int minimum_points{0};
QVector<arglist_t> args = {
use_src_name = opt_rpt_name;
name_digits = 3;
- if (rpt_name_digits && *rpt_name_digits) {
- name_digits = xstrtoi(rpt_name_digits, nullptr, 10);
+ if (!rpt_name_digits.isEmpty()) {
+ name_digits = rpt_name_digits.get_result();
}
- if (opt_waypts != nullptr) {
+ if (opt_waypts) {
current_target = 'W';
- switch (toupper(*opt_waypts)) {
- case 'R':
+ if (opt_waypts.get().startsWith('R', Qt::CaseInsensitive)) {
transform_routes();
if (delete_after) {
route_flush_all_routes();
}
- break;
- case 'T':
+ } else if (opt_waypts.get().startsWith('T', Qt::CaseInsensitive)) {
transform_tracks();
if (delete_after) {
route_flush_all_tracks();
}
- break;
- default:
- fatal(MYNAME ": Invalid option value (%s)!\n", qPrintable(opt_waypts.get()));
+ } else {
+ fatal(MYNAME ": Invalid option value (%s)!\n", qPrintable(opt_waypts));
}
}
- if (opt_routes != nullptr) {
+ if (opt_routes) {
current_target = 'R';
- switch (toupper(*opt_routes)) {
- case 'W':
+ if (opt_routes.get().startsWith('W', Qt::CaseInsensitive)) {
transform_waypoints();
if (delete_after) {
waypt_flush_all();
}
- break;
- case 'T':
+ } else if (opt_routes.get().startsWith('T', Qt::CaseInsensitive)) {
transform_tracks();
if (delete_after) {
route_flush_all_tracks();
}
- break;
- default:
- fatal(MYNAME ": Invalid option value (%s)!\n", qPrintable(opt_routes.get()));
+ } else {
+ fatal(MYNAME ": Invalid option value (%s)!\n", qPrintable(opt_routes));
}
}
- if (opt_tracks != nullptr) {
+ if (opt_tracks) {
current_target = 'T';
- switch (toupper(*opt_tracks)) {
- case 'W':
+ if (opt_tracks.get().startsWith('W', Qt::CaseInsensitive)) {
transform_waypoints();
if (delete_after) {
waypt_flush_all();
}
- break;
- case 'R':
+ } else if (opt_tracks.get().startsWith('R', Qt::CaseInsensitive)) {
transform_routes();
if (delete_after) {
route_flush_all_routes();
}
- break;
- default:
- fatal(MYNAME ": Invalid option value (%s)!\n", qPrintable(opt_tracks.get()));
+ } else {
+ fatal(MYNAME ": Invalid option value (%s)!\n", qPrintable(opt_tracks));
}
}
}
#include "defs.h" // for route_head (ptr only), ARG_NOMINMAX, ARGTY...
#include "filter.h" // for Filter
-#include "option.h" // for OptionCString, OptionBool
+#include "option.h" // for OptionString, OptionBool
#if FILTERS_ENABLED
route_head* current_trk{};
route_head* current_rte{};
- OptionCString opt_routes;
- OptionCString opt_tracks;
- OptionCString opt_waypts;
+ OptionString opt_routes;
+ OptionString opt_tracks;
+ OptionString opt_waypts;
OptionBool opt_delete;
- OptionCString rpt_name_digits;
+ OptionInt rpt_name_digits;
OptionBool opt_rpt_name;
OptionBool opt_timeless;
bool timeless{};
QDateTime
UnicsvFormat::unicsv_adjust_time(const QDate date, const QTime time, bool is_localtime) const
{
- return make_datetime(date, time, is_localtime, opt_utc != nullptr, utc_offset);
+ return make_datetime(date, time, is_localtime, opt_utc, utc_offset);
}
bool
unicsv_detect = (!(global_opts.masked_objective & (WPTDATAMASK | TRKDATAMASK | RTEDATAMASK | POSNDATAMASK)));
unicsv_track = unicsv_route = nullptr;
- unicsv_datum_idx = gt_lookup_datum_index(opt_datum.get(), MYNAME);
+ unicsv_datum_idx = gt_lookup_datum_index(opt_datum, MYNAME);
fin = new gpsbabel::TextStream;
- fin->open(fname, QIODevice::ReadOnly, MYNAME, opt_codec);
+ fin->open(fname, QIODevice::ReadOnly, MYNAME, opt_codec.get().toUtf8());
unicsv_lineno = 0;
if (opt_fields) {
- QString fields = QString(opt_fields).replace('+', ',');
+ QString fields = opt_fields;
+ fields.replace('+', ',');
unicsv_fondle_header(fields);
} else if (buff = fin->readLine(); !buff.isNull()) {
++unicsv_lineno;
unicsv_fieldsep = nullptr;
}
- utc_offset = (opt_utc == nullptr)? 0 : xstrtoi(opt_utc, nullptr, 10) * SECONDS_PER_HOUR;
+ utc_offset = opt_utc? opt_utc.get_result() * SECONDS_PER_HOUR : 0;
}
void
return;
}
QDateTime dt;
- if (opt_utc != nullptr) {
+ if (opt_utc) {
dt = idt.toOffsetFromUtc(utc_offset);
} else {
dt = idt.toLocalTime();
if (unicsv_outp_flags[fld_date]) {
if (wpt->creation_time.toTime_t() >= 2 * SECONDS_PER_DAY) {
QDateTime dt;
- if (opt_utc != nullptr) {
+ if (opt_utc) {
dt = wpt->GetCreationTime().toOffsetFromUtc(utc_offset);
} else {
dt = wpt->GetCreationTime().toLocalTime();
if (unicsv_outp_flags[fld_time]) {
if (wpt->creation_time.isValid()) {
QDateTime dt;
- if (opt_utc != nullptr) {
+ if (opt_utc) {
dt = wpt->GetCreationTime().toOffsetFromUtc(utc_offset);
} else {
dt = wpt->GetCreationTime().toLocalTime();
": option 'fields' is not supported on output");
}
fout = new gpsbabel::TextStream;
- fout->open(fname, QIODevice::WriteOnly, MYNAME, opt_codec);
+ fout->open(fname, QIODevice::WriteOnly, MYNAME, opt_codec.get().toUtf8());
fout->setRealNumberNotation(QTextStream::FixedNotation);
unicsv_outp_flags.reset();
unicsv_fieldsep = kUnicsvFieldSep;
unicsv_waypt_ct = 0;
- if (opt_grid != nullptr) {
- int i;
+ if (!opt_grid.isEmpty()) {
+ bool ok;
- if (sscanf(opt_grid, "%d", &i)) {
+ if (int i = opt_grid.toInt(&ok); ok) {
unicsv_grid_idx = (grid_type) i;
if ((unicsv_grid_idx < GRID_INDEX_MIN) || (unicsv_grid_idx > GRID_INDEX_MAX))
fatal(MYNAME ": Grid index out of range (%d..%d)!\n",
(int)GRID_INDEX_MIN, (int)GRID_INDEX_MAX);
} else {
- unicsv_grid_idx = gt_lookup_grid_type(opt_grid.get(), MYNAME);
+ unicsv_grid_idx = gt_lookup_grid_type(opt_grid, MYNAME);
}
}
{
unicsv_datum_idx = kDatumWGS84; /* internal, becomes CH1903 */
} else {
- unicsv_datum_idx = gt_lookup_datum_index(opt_datum.get(), MYNAME);
+ unicsv_datum_idx = gt_lookup_datum_index(opt_datum, MYNAME);
}
- llprec = xstrtoi(opt_prec, nullptr, 10);
- utc_offset = (opt_utc == nullptr)? 0 : xstrtoi(opt_utc, nullptr, 10) * SECONDS_PER_HOUR;
+ llprec = opt_prec.get_result();
+ utc_offset = opt_utc? opt_utc.get_result() * SECONDS_PER_HOUR : 0;
}
void
#include "defs.h"
#include "format.h" // for Format
#include "geocache.h" // for Geocache, Geocache::status_t
-#include "option.h" // for OptionCString, OptionBool
+#include "option.h" // for OptionString, OptionBool
#include "src/core/textstream.h" // for TextStream
std::bitset<fld_terminator> unicsv_outp_flags;
grid_type unicsv_grid_idx{grid_unknown};
int unicsv_datum_idx{};
- OptionCString opt_datum;
- OptionCString opt_grid;
- OptionCString opt_utc;
+ OptionString opt_datum;
+ OptionString opt_grid;
+ OptionInt opt_utc;
OptionBool opt_filename;
OptionBool opt_format;
- OptionCString opt_prec;
- OptionCString opt_fields;
- OptionCString opt_codec;
+ OptionInt opt_prec;
+ OptionString opt_fields;
+ OptionString opt_codec;
int unicsv_waypt_ct{};
char unicsv_detect{};
int llprec{};
style_list = create_style_vec();
}
-bool Vecs::is_integer(const QString& val)
+int Vecs::integer_base(uint32_t argtype)
{
-#if 1
- /* FIXME: Using scanf to validate input is not recommened.
- * Users may have taken advantage of this flexibilty
- * when interpreting ARGTYPE_INT.
- * INT05-C. Do not use input functions to convert character
- * data if they cannot handle all possible inputs
- */
- // note sscanf doesn't do range checking
- // note some users allow hex input.
- // note some users may interpret trailing data after
- // conversion, typically to denote a unit.
- int test;
- return 1 == sscanf(CSTR(val), "%d", &test);
-#else
- try {
- (void) std::stoi(val.toStdString(), nullptr, 10);
- } catch (const std::invalid_argument&) {
- return false;
- } catch (const std::out_of_range&) {
- return false;
+ int base;
+ switch (argtype & ARGTYPE_BASEMASK) {
+ case ARGTYPE_BASE_AUTO:
+ base = 0;
+ break;
+ case ARGTYPE_BASE_16:
+ base = 16;
+ break;
+ case ARGTYPE_BASE_10:
+ default:
+ base = 10;
}
- return true;
-#endif
+ return base;
+
}
-bool Vecs::is_float(const QString& val)
+bool Vecs::trailing_data_allowed(uint32_t argtype)
{
-#if 1
- /* FIXME: Using scanf to validate input is not recommened.
- * Users may have taken advantage of this flexibilty
- * when interpreting ARGTYPE_FLOAT.
- * INT05-C. Do not use input functions to convert character
- * data if they cannot handle all possible inputs
- */
- // note sscanf doesn't do range checking
- // note some users may interpret trailing data after
- // conversion, typically to denote a unit.
- double test;
- return 1 == sscanf(CSTR(val), "%lf", &test);
-#else
- try {
- (void) std::stod(val.toStdString(), nullptr);
- } catch (const std::invalid_argument&) {
- return false;
- } catch (const std::out_of_range&) {
- return false;
- }
- return true;
-#endif
+ return (argtype & ARGTYPE_ALLOW_TRAILING_DATA) == ARGTYPE_ALLOW_TRAILING_DATA;
+}
+
+bool Vecs::is_integer(const QString& val, const QString& id, uint32_t argtype)
+{
+ bool ok;
+ int base = integer_base(argtype);
+ QString end;
+ QString* endp = trailing_data_allowed(argtype) ? &end : nullptr;
+ (void) parse_integer(val, id, &ok, endp, base);
+ return ok;
+}
+
+int Vecs::convert_integer(const QString& val, const QString& id, QString* end, int base)
+{
+ // Fatal on conversion error
+ constexpr bool* dieonerror = nullptr;
+ return parse_integer(val, id, dieonerror, end, base);
+}
+
+bool Vecs::is_float(const QString& val, const QString& id, uint32_t argtype)
+{
+ bool ok;
+ QString end;
+ QString* endp = trailing_data_allowed(argtype) ? &end : nullptr;
+ (void) parse_double(val, id, &ok, endp);
+ return ok;
+}
+
+double Vecs::convert_float(const QString& val, const QString& id, QString* end)
+{
+ // Fatal on conversion error
+ constexpr bool* dieonerror = nullptr;
+ return parse_double(val, id, dieonerror, end);
}
bool Vecs::is_bool(const QString& val)
void Vecs::assign_option(const QString& module, arglist_t& arg, const QString& val)
{
+ QString id = QStringLiteral("%1(%2)").arg(module, arg.argstring);
+
if (arg.argval == nullptr) {
- fatal("%s: No local variable defined for option \"%s\"!\n", qPrintable(module), qPrintable(arg.argstring));
+ fatal("%s: Program error - No local variable defined for option.\n", qPrintable(id));
}
arg.argval->reset();
+ arg.argval->set_id(id);
if (val.isNull()) {
return;
QString rval(val);
- switch (arg.argtype & ARGTYPE_TYPEMASK) {
- case ARGTYPE_INT:
+ QString end;
+ QString* endp = trailing_data_allowed(arg.argtype)? &end: nullptr;
+
+ if (auto* int_option = dynamic_cast<OptionInt*>(arg.argval); int_option != nullptr) {
+ int result;
if (val.isEmpty()) {
rval = '0';
+ result = 0;
} else {
- if (!is_integer(val)) {
- fatal("%s: Invalid parameter value \"%s\" for option %s!\n", qPrintable(module), qPrintable(val), qPrintable(arg.argstring));
- }
+ // will fatal on conversion error
+ result = convert_integer(val, id, endp, integer_base(arg.argtype));
}
- break;
- case ARGTYPE_FLOAT:
+ int_option->set_result(result, end);
+ } else if (auto* double_option = dynamic_cast<OptionDouble*>(arg.argval); double_option != nullptr) {
+ double result;
if (val.isEmpty()) {
rval = '0';
+ result = 0.0;
} else {
- if (!is_float(val)) {
- fatal("%s: Invalid parameter value \"%s\" for option %s!\n", qPrintable(module), qPrintable(val), qPrintable(arg.argstring));
- }
+ // will fatal on conversion error
+ result = convert_float(val, id, endp);
}
- break;
- case ARGTYPE_BOOL:
+ double_option->set_result(result, end);
+ } else if (auto* bool_option = dynamic_cast<OptionBool*>(arg.argval); bool_option != nullptr) {
if (val.isEmpty()) {
rval = '1';
} else {
rval = '1';
}
} else {
- warning("%s :Invalid logical value \"%s\" for option %s!\n", qPrintable(module), qPrintable(val), qPrintable(arg.argstring));
+ warning("%s: Invalid logical value \"%s\".\n", qPrintable(id), qPrintable(val));
rval = '0';
}
}
}
- break;
}
arg.argval->set(rval);
}
#endif
for (const auto& arg : *args) {
+ QString id = QStringLiteral("%1(%2)").arg(name, arg.argstring);
if (arg.argval == nullptr) {
Warning() << name << "option" << arg.argstring << "does not point to an Option instance.";
ok = false;
}
- if ((arg.argtype & ARGTYPE_TYPEMASK) == ARGTYPE_INT) {
- if (!arg.defaultvalue.isNull() && !is_integer(arg.defaultvalue)) {
+ if (const auto* int_option = dynamic_cast<const OptionInt*>(arg.argval); int_option != nullptr) {
+ if (trailing_data_allowed(arg.argtype)) {
+ // GUI QIntValidator will reject input with trailing data.
+ if ((arg.argtype & ARGTYPE_TYPEMASK) != ARGTYPE_STRING) {
+ Warning() << name << "OptionInt with trailing data" << arg.argstring << "is not of ARGTYPE_STRING.";
+ ok = false;
+ }
+ } else {
+ if ((arg.argtype & ARGTYPE_TYPEMASK) != ARGTYPE_INT) {
+ Warning() << name << "OptionInt option without trailing data" << arg.argstring << "is not of ARGTYPE_INT.";
+ ok = false;
+ }
+ }
+
+ if (!arg.defaultvalue.isNull() && !is_integer(arg.defaultvalue, id, arg.argtype)) {
Warning() << name << "Int option" << arg.argstring << "default value" << arg.defaultvalue << "is not an integer.";
ok = false;
}
- if (!arg.minvalue.isNull() && !is_integer(arg.minvalue)) {
+ if (!arg.minvalue.isNull() && !is_integer(arg.minvalue, id, arg.argtype)) {
Warning() << name << "Int option" << arg.argstring << "minimum value" << arg.minvalue << "is not an integer.";
ok = false;
}
- if (!arg.maxvalue.isNull() && !is_integer(arg.maxvalue)) {
+ if (!arg.maxvalue.isNull() && !is_integer(arg.maxvalue, id, arg.argtype)) {
Warning() << name << "Int option" << arg.argstring << "maximum value" << arg.maxvalue << "is not an integer.";
ok = false;
}
- } else if ((arg.argtype & ARGTYPE_TYPEMASK) == ARGTYPE_FLOAT) {
- if (!arg.defaultvalue.isNull() && !is_float(arg.defaultvalue)) {
+ } else if (const auto* double_option = dynamic_cast<const OptionDouble*>(arg.argval); double_option != nullptr) {
+ if (trailing_data_allowed(arg.argtype)) {
+ // GUI QDoubleValidator will reject input with trailing data.
+ if ((arg.argtype & ARGTYPE_TYPEMASK) != ARGTYPE_STRING) {
+ Warning() << name << "OptionDouble with trailing data" << arg.argstring << "is not of ARGTYPE_STRING.";
+ ok = false;
+ }
+ } else {
+ if ((arg.argtype & ARGTYPE_TYPEMASK) != ARGTYPE_FLOAT) {
+ Warning() << name << "OptionDouble without trailing data" << arg.argstring << "is not of ARGTYPE_FLOAT.";
+ ok = false;
+ }
+ }
+
+ if (!arg.defaultvalue.isNull() && !is_float(arg.defaultvalue, id, arg.argtype)) {
Warning() << name << "Float option" << arg.argstring << "default value" << arg.defaultvalue << "is not an float.";
ok = false;
}
- if (!arg.minvalue.isNull() && !is_float(arg.minvalue)) {
+ if (!arg.minvalue.isNull() && !is_float(arg.minvalue, id, arg.argtype)) {
Warning() << name << "Float option" << arg.argstring << "minimum value" << arg.minvalue << "is not an float.";
ok = false;
}
- if (!arg.maxvalue.isNull() && !is_float(arg.maxvalue)) {
+ if (!arg.maxvalue.isNull() && !is_float(arg.maxvalue, id, arg.argtype)) {
Warning() << name << "Float option" << arg.argstring << "maximum value" << arg.maxvalue << "is not an float.";
ok = false;
}
- } else if ((arg.argtype & ARGTYPE_TYPEMASK) == ARGTYPE_BOOL) {
+ } else if (const auto* bool_option = dynamic_cast<const OptionBool*>(arg.argval); bool_option != nullptr) {
+ if ((arg.argtype & ARGTYPE_TYPEMASK) != ARGTYPE_BOOL) {
+ Warning() << name << "OptionBool" << arg.argstring << "is not of ARGTYPE_BOOL.";
+ ok = false;
+ }
+
if (!arg.defaultvalue.isNull() && !is_bool(arg.defaultvalue)) {
Warning() << name << "Bool option" << arg.argstring << "default value" << arg.defaultvalue << "is not an bool.";
ok = false;
Warning() << name << "Bool option" << arg.argstring << "maximum value" << arg.maxvalue << "is not an bool.";
ok = false;
}
- if (const auto* opt = dynamic_cast<const OptionBool*>(arg.argval); opt == nullptr) {
- Warning() << name << "Bool option" << arg.argstring << "argval is not of class OptionBool";
+ } else if (const auto* str_option = dynamic_cast<const OptionString*>(arg.argval); str_option != nullptr) {
+ if (((arg.argtype & ARGTYPE_TYPEMASK) != ARGTYPE_STRING) &&
+ ((arg.argtype & ARGTYPE_TYPEMASK) != ARGTYPE_FILE) &&
+ ((arg.argtype & ARGTYPE_TYPEMASK) != ARGTYPE_OUTFILE) &&
+ ((arg.argtype & ARGTYPE_TYPEMASK) != ARGTYPE_UNKNOWN)) {
+ Warning() << name << "OptionString" << arg.argstring << "is not of ARGTYPE STRING, FILE, OUTFILE or UNKNOWN.";
ok = false;
}
+ } else {
+ Warning() << name << "Unexpected Option type" << arg.argstring << ".";
+ ok = false;
}
- if ((arg.argtype & ARGTYPE_TYPEMASK) != ARGTYPE_BOOL) {
- if (const auto* opt = dynamic_cast<const OptionBool*>(arg.argval); opt != nullptr) {
- Warning() << name << "non Bool option" << arg.argstring << "argval is of class OptionBool";
- ok = false;
- }
+
+ switch (arg.argtype & ARGTYPE_TYPEMASK) {
+ case ARGTYPE_INT:
+ case ARGTYPE_FLOAT:
+ case ARGTYPE_BOOL:
+ case ARGTYPE_STRING:
+ case ARGTYPE_FILE:
+ case ARGTYPE_OUTFILE:
+ break;
+ case ARGTYPE_UNKNOWN:
+ default:
+ Warning() << name << "Unknown ARGTYPE for << arg.argstring.";
+ ok = false;
+ break;
}
}
}
/* Member Functions */
- static bool is_integer(const QString& val);
- static bool is_float(const QString& val);
+ static int integer_base(uint32_t argtype);
+ static bool trailing_data_allowed(uint32_t argtype);
+ static bool is_integer(const QString& val, const QString& id, uint32_t argtype);
+ static int convert_integer(const QString& val, const QString& id, QString* end, int base);
+ static bool is_float(const QString& val, const QString& id, uint32_t argtype);
+ static double convert_float(const QString& val, const QString& id, QString* end);
static bool is_bool(const QString& val);
static QVector<style_vec_t> create_style_vec();
QVector<vecinfo_t> sort_and_unify_vecs() const;
QDateTime
XcsvFormat::xcsv_adjust_time(const QDate date, const QTime time, bool is_localtime) const
{
- return make_datetime(date, time, is_localtime, opt_utc != nullptr, utc_offset);
+ return make_datetime(date, time, is_localtime, opt_utc, utc_offset);
}
/*
fatal(MYNAME ": XCSV input style not declared. Use ... -i xcsv,style=path/to/file.style\n");
}
- xcsv_style = new XcsvStyle(XcsvStyle::xcsv_read_style(styleopt.get()));
+ xcsv_style = new XcsvStyle(XcsvStyle::xcsv_read_style(styleopt));
}
if ((xcsv_style->datatype == 0) || (xcsv_style->datatype == wptdata)) {
xcsv_file->fname = fname;
QString datum_name;
- if (opt_datum != nullptr) {
+ if (opt_datum) {
datum_name = opt_datum;
} else if (!xcsv_style->gps_datum_name.isEmpty()) {
datum_name = xcsv_style->gps_datum_name;
fatal(MYNAME ": datum \"%s\" is not supported.", qPrintable(datum_name));
}
- utc_offset = (opt_utc == nullptr)? 0 : xstrtoi(opt_utc, nullptr, 10) * SECONDS_PER_HOUR;
+ utc_offset = opt_utc? opt_utc.get_result() * SECONDS_PER_HOUR : 0;
}
void
fatal(MYNAME ": XCSV output style not declared. Use ... -o xcsv,style=path/to/file.style\n");
}
- xcsv_style = new XcsvStyle(XcsvStyle::xcsv_read_style(styleopt.get()));
+ xcsv_style = new XcsvStyle(XcsvStyle::xcsv_read_style(styleopt));
}
xcsv_file = new XcsvFile;
if (global_opts.synthesize_shortnames) {
if (snlenopt) {
- xcsv_file->mkshort_handle.set_length(xstrtoi(snlenopt, nullptr, 10));
+ xcsv_file->mkshort_handle.set_length(snlenopt.get_result());
}
if (snwhiteopt.has_value()) {
}
QString datum_name;
- if (opt_datum != nullptr) {
+ if (opt_datum) {
datum_name = opt_datum;
} else if (!xcsv_style->gps_datum_name.isEmpty()) {
datum_name = xcsv_style->gps_datum_name;
#include "format.h" // for Format
#include "garmin_fs.h" // for garmin_fs_t
#include "mkshort.h" // for MakeShort
-#include "option.h" // for OptionCString, OptionBool
+#include "option.h" // for OptionString, OptionBool
#include "src/core/datetime.h" // for DateTime
#include "src/core/textstream.h" // for TextStream
const route_head* csv_track = nullptr;
const route_head* csv_route = nullptr;
- OptionCString styleopt;
- OptionCString snlenopt;
+ OptionString styleopt;
+ OptionInt snlenopt;
OptionBool snwhiteopt;
OptionBool snupperopt;
OptionBool snuniqueopt;
OptionBool prefer_shortnames;
- OptionCString xcsv_urlbase;
- OptionCString opt_datum;
- OptionCString opt_utc;
+ OptionString xcsv_urlbase;
+ OptionString opt_datum;
+ OptionInt opt_utc;
int utc_offset{};
QString intstylefile;